public IEnumerable <IPublishedContent> ConvertSearchResultToPublishedContentWithTemplate(
            IEnumerable <SearchResult> rawSearchResults, IPublishedContentCache cache, UmbracoContext context)
        {
            //remove duplicated nodes/ids - fixed with hashset
            var nodesWithOutDuplicates  = new HashSet <IPublishedContent>();
            var excludedDocTypesAliases = new HashSet <string>(_configHelper.GetValue("SiteSearchExcludedDocTypes").Split(','));

            //I would know that it's under the correct Language because of the parent ID of the IndexSet
            var searchResults = rawSearchResults.ToList();

            foreach (var r in searchResults)
            {
                var content = cache.GetById(context, false, r.Id);
                if (content != null)
                {
                    IPublishedContent nodeToAdd = content;

                    if (content.TemplateId == 0)
                    {
                        nodeToAdd = _umbracoTree.GetFirstParentWithTemplate(content);
                    }

                    if (nodeToAdd != null && !excludedDocTypesAliases.Contains(nodeToAdd.DocumentTypeAlias))
                    {
                        nodesWithOutDuplicates.Add(nodeToAdd);
                    }
                }
            }

            return(nodesWithOutDuplicates.ToList());
        }
Example #2
0
    private void StoreOldRoute(IContent entity, OldRoutesDictionary oldRoutes)
    {
        if (!_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot))
        {
            return;
        }

        IPublishedContentCache?contentCache  = publishedSnapshot?.Content;
        IPublishedContent?     entityContent = contentCache?.GetById(entity.Id);

        if (entityContent is null)
        {
            return;
        }

        // get the default affected cultures by going up the tree until we find the first culture variant entity (default to no cultures)
        var defaultCultures = entityContent.AncestorsOrSelf().FirstOrDefault(a => a.Cultures.Any())?.Cultures.Keys
                              .ToArray()
                              ?? Array.Empty <string>();

        foreach (IPublishedContent publishedContent in entityContent.DescendantsOrSelf(_variationContextAccessor))
        {
            // if this entity defines specific cultures, use those instead of the default ones
            IEnumerable <string> cultures =
                publishedContent.Cultures.Any() ? publishedContent.Cultures.Keys : defaultCultures;

            foreach (var culture in cultures)
            {
                var route = contentCache?.GetRouteById(publishedContent.Id, culture);
                if (!IsNotRoute(route))
                {
                    oldRoutes[new ContentIdAndCulture(publishedContent.Id, culture)] = new ContentKeyAndOldRoute(publishedContent.Key, route !);
                }
                else if (string.IsNullOrEmpty(culture))
                {
                    // Retry using all languages, if this is invariant but has a variant ancestor
                    var languages = _localizationService.GetAllLanguages();
                    foreach (var language in languages)
                    {
                        route = contentCache?.GetRouteById(publishedContent.Id, language.IsoCode);
                        if (!IsNotRoute(route))
                        {
                            oldRoutes[new ContentIdAndCulture(publishedContent.Id, language.IsoCode)] =
                                new ContentKeyAndOldRoute(publishedContent.Key, route !);
                        }
                    }
                }
            }
        }
    }
Example #3
0
        private void StoreOldRoute(IContent entity, OldRoutesDictionary oldRoutes)
        {
            if (!_publishedSnapshotAccessor.TryGetPublishedSnapshot(out var publishedSnapshot))
            {
                return;
            }

            IPublishedContentCache?contentCache  = publishedSnapshot?.Content;
            IPublishedContent?     entityContent = contentCache?.GetById(entity.Id);

            if (entityContent is null)
            {
                return;
            }

            // get the default affected cultures by going up the tree until we find the first culture variant entity (default to no cultures)
            var defaultCultures = entityContent.AncestorsOrSelf()?.FirstOrDefault(a => a.Cultures.Any())?.Cultures.Keys.ToArray()
                                  ?? Array.Empty <string>();

            foreach (IPublishedContent publishedContent in entityContent.DescendantsOrSelf(_variationContextAccessor))
            {
                // if this entity defines specific cultures, use those instead of the default ones
                IEnumerable <string> cultures = publishedContent.Cultures.Any() ? publishedContent.Cultures.Keys : defaultCultures;

                foreach (var culture in cultures)
                {
                    var route = contentCache?.GetRouteById(publishedContent.Id, culture);
                    if (IsNotRoute(route))
                    {
                        continue;
                    }

                    oldRoutes[new ContentIdAndCulture(publishedContent.Id, culture)] = new ContentKeyAndOldRoute(publishedContent.Key, route !);
                }
            }
        }
Example #4
0
        private IPublishedContent?FindContentByAlias(IPublishedContentCache?cache, int rootNodeId, string?culture, string alias)
        {
            if (alias == null)
            {
                throw new ArgumentNullException(nameof(alias));
            }

            // the alias may be "foo/bar" or "/foo/bar"
            // there may be spaces as in "/foo/bar,  /foo/nil"
            // these should probably be taken care of earlier on

            // TODO: can we normalize the values so that they contain no whitespaces, and no leading slashes?
            // and then the comparisons in IsMatch can be way faster - and allocate way less strings
            const string propertyAlias = Constants.Conventions.Content.UrlAlias;

            var test1 = alias.TrimStart(Constants.CharArrays.ForwardSlash) + ",";
            var test2 = ",/" + test1; // test2 is ",/alias,"

            test1 = "," + test1;      // test1 is ",alias,"

            bool IsMatch(IPublishedContent c, string a1, string a2)
            {
                // this basically implements the original XPath query ;-(
                //
                // "//* [@isDoc and (" +
                // "contains(concat(',',translate(umbracoUrlAlias, ' ', ''),','),',{0},')" +
                // " or contains(concat(',',translate(umbracoUrlAlias, ' ', ''),','),',/{0},')" +
                // ")]"
                if (!c.HasProperty(propertyAlias))
                {
                    return(false);
                }

                IPublishedProperty?p = c.GetProperty(propertyAlias);
                var    varies        = p !.PropertyType?.VariesByCulture();
                string?v;

                if (varies ?? false)
                {
                    if (!c.HasCulture(culture))
                    {
                        return(false);
                    }

                    v = c.Value <string>(_publishedValueFallback, propertyAlias, culture);
                }
                else
                {
                    v = c.Value <string>(_publishedValueFallback, propertyAlias);
                }

                if (string.IsNullOrWhiteSpace(v))
                {
                    return(false);
                }

                v = "," + v.Replace(" ", string.Empty) + ",";
                return(v.InvariantContains(a1) || v.InvariantContains(a2));
            }

            // TODO: even with Linq, what happens below has to be horribly slow
            // but the only solution is to entirely refactor URL providers to stop being dynamic
            if (rootNodeId > 0)
            {
                IPublishedContent?rootNode = cache?.GetById(rootNodeId);
                return(rootNode?.Descendants(_variationContextAccessor).FirstOrDefault(x => IsMatch(x, test1, test2)));
            }

            if (cache is not null)
            {
                foreach (IPublishedContent rootContent in cache.GetAtRoot())
                {
                    IPublishedContent?c = rootContent.DescendantsOrSelf(_variationContextAccessor).FirstOrDefault(x => IsMatch(x, test1, test2));
                    if (c != null)
                    {
                        return(c);
                    }
                }
            }

            return(null);
        }