Exemple #1
0
        /// <summary>
        /// This will return the URL that is returned by the assigned custom <see cref="IPublishedContent"/> if this is a custom route
        /// </summary>
        public UrlInfo GetUrl(UmbracoContext umbracoContext, IPublishedContent content, UrlProviderMode mode, string culture, Uri current)
        {
            if (umbracoContext?.PublishedRequest?.PublishedContent == null)
            {
                return(null);
            }
            if (umbracoContext.HttpContext?.Request?.RequestContext?.RouteData?.DataTokens == null)
            {
                return(null);
            }
            if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey(Core.Constants.Web.CustomRouteDataToken) == false)
            {
                return(null);
            }


            //If we get this far, it means it's a custom route with published content assigned, check if the id being requested for is the same id as the assigned published content
            //NOTE: This looks like it might cause an infinite loop because PublishedContentBase.Url calls into UmbracoContext.Current.UrlProvider.GetUrl which calls back into the IUrlProvider pipeline
            // but the specific purpose of this is that a developer is using their own IPublishedContent that returns a specific Url and doesn't go back into the UrlProvider pipeline.
            //TODO: We could put a try/catch here just in case, else we could do some reflection checking to see if the implementation is PublishedContentBase and the Url property is not overridden.
            return(UrlInfo.Url(
                       content.Id == umbracoContext.PublishedRequest.PublishedContent.Id
                    ? umbracoContext.PublishedRequest.PublishedContent.GetUrl(culture)
                    : null,
                       culture));
        }
        /// <inheritdoc />
        public virtual UrlInfo GetMediaUrl(UmbracoContext umbracoContext, IPublishedContent content,
                                           string propertyAlias, UrlMode mode, string culture, Uri current)
        {
            var prop = content.GetProperty(propertyAlias);

            // get the raw source value since this is what is used by IDataEditorWithMediaPath for processing
            var value = prop?.GetSourceValue(culture);

            if (value == null)
            {
                return(null);
            }

            var    propType = prop.PropertyType;
            string path     = null;

            if (_propertyEditors.TryGet(propType.EditorAlias, out var editor) &&
                editor is IDataEditorWithMediaPath dataEditor)
            {
                path = dataEditor.GetMediaPath(value);
            }

            var url = AssembleUrl(path, current, mode);

            return(url == null ? null : UrlInfo.Url(url.ToString(), culture));
        }
Exemple #3
0
        /// <inheritdoc />
        public virtual UrlInfo GetMediaUrl(UmbracoContext umbracoContext, IPublishedContent content,
                                           string propertyAlias,
                                           UrlMode mode, string culture, Uri current)
        {
            var prop  = content.GetProperty(propertyAlias);
            var value = prop?.GetValue(culture);

            if (value == null)
            {
                return(null);
            }

            var    propType = prop.PropertyType;
            string path     = null;

            switch (propType.EditorAlias)
            {
            case Constants.PropertyEditors.Aliases.UploadField:
                path = value.ToString();
                break;

            case Constants.PropertyEditors.Aliases.ImageCropper:
                //get the url from the json format
                path = value is ImageCropperValue stronglyTyped ? stronglyTyped.Src : value.ToString();
                break;
            }

            var url = AssembleUrl(path, current, mode);

            return(url == null ? null : UrlInfo.Url(url.ToString(), culture));
        }
Exemple #4
0
        /// <summary>
        /// Tries to return a <see cref="UrlInfo"/> for each culture for the content while detecting collisions/errors
        /// </summary>
        /// <param name="content"></param>
        /// <param name="cultures"></param>
        /// <param name="publishedRouter"></param>
        /// <param name="umbracoContext"></param>
        /// <param name="contentService"></param>
        /// <param name="textService"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        private static IEnumerable <UrlInfo> GetContentUrlsByCulture(IContent content,
                                                                     IEnumerable <string> cultures,
                                                                     PublishedRouter publishedRouter,
                                                                     UmbracoContext umbracoContext,
                                                                     IContentService contentService,
                                                                     ILocalizedTextService textService,
                                                                     ILogger logger)
        {
            foreach (var culture in cultures)
            {
                // if content is variant, and culture is not published, skip
                if (content.ContentType.VariesByCulture() && !content.IsCulturePublished(culture))
                {
                    continue;
                }

                // if it's variant and culture is published, or if it's invariant, proceed

                string url;
                try
                {
                    url = umbracoContext.UrlProvider.GetUrl(content.Id, culture);
                }
                catch (Exception ex)
                {
                    logger.Error <UrlProvider>(ex, "GetUrl exception.");
                    url = "#ex";
                }

                switch (url)
                {
                // deal with 'could not get the url'
                case "#":
                    yield return(HandleCouldNotGetUrl(content, culture, contentService, textService));

                    break;

                // deal with exceptions
                case "#ex":
                    yield return(UrlInfo.Message(textService.Localize("content/getUrlException"), culture));

                    break;

                // got a url, deal with collisions, add url
                default:
                    if (DetectCollision(content, url, culture, umbracoContext, publishedRouter, textService, out var urlInfo))     // detect collisions, etc
                    {
                        yield return(urlInfo);
                    }
                    else
                    {
                        yield return(UrlInfo.Url(url, culture));
                    }
                    break;
                }
            }
        }
        /// <summary>
        /// Gets the other urls of a published content.
        /// </summary>
        /// <param name="umbracoContext">The Umbraco context.</param>
        /// <param name="id">The published content id.</param>
        /// <param name="current">The current absolute url.</param>
        /// <returns>The other urls for the published content.</returns>
        /// <remarks>
        /// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
        /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
        /// </remarks>
        public virtual IEnumerable <UrlInfo> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
        {
            var node = umbracoContext.ContentCache.GetById(id);

            if (node == null)
            {
                yield break;
            }

            var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper);

            // look for domains, walking up the tree
            var n          = node;
            var domainUris = domainHelper.DomainsForNode(n.Id, current, false);

            while (domainUris == null && n != null) // n is null at root
            {
                n          = n.Parent;              // move to parent node
                domainUris = n == null ? null : domainHelper.DomainsForNode(n.Id, current, excludeDefault: true);
            }

            // no domains = exit
            if (domainUris == null)
            {
                yield break;
            }

            foreach (var d in domainUris)
            {
                var culture = d?.Culture?.Name;

                //although we are passing in culture here, if any node in this path is invariant, it ignores the culture anyways so this is ok
                var route = umbracoContext.ContentCache.GetRouteById(id, culture);
                if (route == null)
                {
                    continue;
                }

                //need to strip off the leading ID for the route if it exists (occurs if the route is for a node with a domain assigned)
                var pos  = route.IndexOf('/');
                var path = pos == 0 ? route : route.Substring(pos);

                var uri = new Uri(CombinePaths(d.Uri.GetLeftPart(UriPartial.Path), path));
                uri = UriUtility.UriFromUmbraco(uri, _globalSettings, _requestSettings);
                yield return(UrlInfo.Url(uri.ToString(), culture));
            }
        }
        internal UrlInfo GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlMode mode, string culture)
        {
            if (string.IsNullOrWhiteSpace(route))
            {
                _logger.Debug <DefaultUrlProvider>("Couldn't find any page with nodeId={NodeId}. This is most likely caused by the page not being published.", id);
                return(null);
            }

            // extract domainUri and path
            // route is /<path> or <domainRootId>/<path>
            var pos       = route.IndexOf('/');
            var path      = pos == 0 ? route : route.Substring(pos);
            var domainUri = pos == 0
                ? null
                : DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, int.Parse(route.Substring(0, pos)), current, culture);

            // assemble the URL from domainUri (maybe null) and path
            var url = AssembleUrl(domainUri, path, current, mode).ToString();

            return(UrlInfo.Url(url, culture));
        }
Exemple #7
0
        /// <summary>
        /// Gets the other urls of a published content.
        /// </summary>
        /// <param name="umbracoContext">The Umbraco context.</param>
        /// <param name="id">The published content id.</param>
        /// <param name="current">The current absolute url.</param>
        /// <returns>The other urls for the published content.</returns>
        /// <remarks>
        /// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
        /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
        /// </remarks>
        public IEnumerable <UrlInfo> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
        {
            var node = umbracoContext.Content.GetById(id);

            if (node == null)
            {
                yield break;
            }

            if (!node.HasProperty(Constants.Conventions.Content.UrlAlias))
            {
                yield break;
            }

            // look for domains, walking up the tree
            var n          = node;
            var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, false);

            while (domainUris == null && n != null) // n is null at root
            {
                // move to parent node
                n          = n.Parent;
                domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, excludeDefault: false);
            }

            // determine whether the alias property varies
            var varies = node.GetProperty(Constants.Conventions.Content.UrlAlias).PropertyType.VariesByCulture();

            if (domainUris == null)
            {
                // no domain
                // if the property is invariant, then url "/<alias>" is ok
                // if the property varies, then what are we supposed to do?
                //  the content finder may work, depending on the 'current' culture,
                //  but there's no way we can return something meaningful here
                if (varies)
                {
                    yield break;
                }

                var umbracoUrlName = node.Value <string>(Constants.Conventions.Content.UrlAlias);
                var aliases        = umbracoUrlName?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                if (aliases == null || aliases.Any() == false)
                {
                    yield break;
                }

                foreach (var alias in aliases.Distinct())
                {
                    var path = "/" + alias;
                    var uri  = new Uri(path, UriKind.Relative);
                    yield return(UrlInfo.Url(UriUtility.UriFromUmbraco(uri, _globalSettings, _requestConfig).ToString()));
                }
            }
            else
            {
                // some domains: one url per domain, which is "<domain>/<alias>"
                foreach (var domainUri in domainUris)
                {
                    // if the property is invariant, get the invariant value, url is "<domain>/<invariant-alias>"
                    // if the property varies, get the variant value, url is "<domain>/<variant-alias>"

                    // but! only if the culture is published, else ignore
                    if (varies && !node.HasCulture(domainUri.Culture.Name))
                    {
                        continue;
                    }

                    var umbracoUrlName = varies
                        ? node.Value <string>(Constants.Conventions.Content.UrlAlias, culture: domainUri.Culture.Name)
                        : node.Value <string>(Constants.Conventions.Content.UrlAlias);

                    var aliases = umbracoUrlName?.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                    if (aliases == null || aliases.Any() == false)
                    {
                        continue;
                    }

                    foreach (var alias in aliases.Distinct())
                    {
                        var path = "/" + alias;
                        var uri  = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path));
                        yield return(UrlInfo.Url(UriUtility.UriFromUmbraco(uri, _globalSettings, _requestConfig).ToString(), domainUri.Culture.Name));
                    }
                }
            }
        }