diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index c8bb55c44c..92779c18fa 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -174,100 +174,98 @@ public class EntityController : UmbracoAuthorizedJsonController return ExamineSearch(query, type, searchFrom, ignoreUserStartNodes); } - /// - /// Searches for all content that the user is allowed to see (based on their allowed sections) - /// - /// - /// - /// - /// Even though a normal entity search will allow any user to search on a entity type that they may not have access to - /// edit, we need - /// to filter these results to the sections they are allowed to edit since this search function is explicitly for the - /// global search - /// so if we showed entities that they weren't allowed to edit they would get errors when clicking on the result. - /// The reason a user is allowed to search individual entity types that they are not allowed to edit is because those - /// search - /// methods might be used in things like pickers in the content editor. - /// - [HttpGet] - public async Task> SearchAll(string query) - { - var result = new ConcurrentDictionary(); - - if (string.IsNullOrEmpty(query)) + /// + /// Searches for all content that the user is allowed to see (based on their allowed sections) + /// + /// + /// + /// + /// Even though a normal entity search will allow any user to search on a entity type that they may not have access to + /// edit, we need + /// to filter these results to the sections they are allowed to edit since this search function is explicitly for the + /// global search + /// so if we showed entities that they weren't allowed to edit they would get errors when clicking on the result. + /// The reason a user is allowed to search individual entity types that they are not allowed to edit is because those + /// search + /// methods might be used in things like pickers in the content editor. + /// + [HttpGet] + public async Task> SearchAll(string query) { - return result; - } - - var culture = ClientCulture(); - var allowedSections = _backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.AllowedSections.ToArray(); - - var searchTasks = new List(); - foreach (KeyValuePair searchableTree in _searchableTreeCollection - .SearchableApplicationTrees.OrderBy(t => t.Value.SortOrder)) - { - if (allowedSections?.Contains(searchableTree.Value.AppAlias) ?? false) + if (string.IsNullOrEmpty(query)) { - Tree? tree = _treeService.GetByAlias(searchableTree.Key); - if (tree == null) - { - continue; //shouldn't occur - } + return new Dictionary(); + } - var rootNodeDisplayName = Tree.GetRootNodeDisplayName(tree, _localizedTextService); - if (rootNodeDisplayName is not null) + var culture = ClientCulture(); + var allowedSections = _backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.AllowedSections.ToArray(); + + var searchTasks = new List>>(); + foreach (KeyValuePair searchableTree in _searchableTreeCollection + .SearchableApplicationTrees.OrderBy(t => t.Value.SortOrder)) + { + if (allowedSections?.Contains(searchableTree.Value.AppAlias) ?? false) { - searchTasks.Add(ExecuteSearchAsync(query, culture, searchableTree, rootNodeDisplayName, result)); + Tree? tree = _treeService.GetByAlias(searchableTree.Key); + if (tree == null) + { + continue; //shouldn't occur + } + + var rootNodeDisplayName = Tree.GetRootNodeDisplayName(tree, _localizedTextService); + if (rootNodeDisplayName is not null) + { + searchTasks.Add(ExecuteSearchAsync(query, culture, searchableTree, rootNodeDisplayName)); + } } } + + var taskResults = await Task.WhenAll(searchTasks); + + return new Dictionary(taskResults); } - await Task.WhenAll(searchTasks); - return result; - } - - private static async Task ExecuteSearchAsync( - string query, - string? culture, - KeyValuePair searchableTree, - string rootNodeDisplayName, - ConcurrentDictionary result) - { - ISearchableTree searcher = searchableTree.Value.SearchableTree; - const int pageSize = 200; - IEnumerable results = ( - searcher is ISearchableTreeWithCulture searcherWithCulture - ? await searcherWithCulture.SearchAsync(query, pageSize, 0, culture: culture) - : await searcher.SearchAsync(query, pageSize, 0)) - .WhereNotNull(); - - var searchResult = new TreeSearchResult + private static async Task> ExecuteSearchAsync( + string query, + string? culture, + KeyValuePair searchableTree, + string rootNodeDisplayName) { - Results = results, - TreeAlias = searchableTree.Key, - AppAlias = searchableTree.Value.AppAlias, - JsFormatterService = searchableTree.Value.FormatterService, - JsFormatterMethod = searchableTree.Value.FormatterMethod - }; + ISearchableTree searcher = searchableTree.Value.SearchableTree; + const int pageSize = 200; + IEnumerable results = ( + searcher is ISearchableTreeWithCulture searcherWithCulture + ? await searcherWithCulture.SearchAsync(query, pageSize, 0, culture: culture) + : await searcher.SearchAsync(query, pageSize, 0)) + .WhereNotNull(); - result.AddOrUpdate(rootNodeDisplayName, _ => searchResult, (_, _) => searchResult); - } + var searchResult = new TreeSearchResult + { + Results = results, + TreeAlias = searchableTree.Key, + AppAlias = searchableTree.Value.AppAlias, + JsFormatterService = searchableTree.Value.FormatterService, + JsFormatterMethod = searchableTree.Value.FormatterMethod + }; - /// - /// Gets the path for a given node ID - /// - /// - /// - /// - public IConvertToActionResult GetPath(int id, UmbracoEntityTypes type) - { - ActionResult foundContentResult = GetResultForId(id, type); - EntityBasic? foundContent = foundContentResult.Value; - if (foundContent is null) - { - return foundContentResult; + return new KeyValuePair(rootNodeDisplayName, searchResult); } + /// + /// Gets the path for a given node ID + /// + /// + /// + /// + public IConvertToActionResult GetPath(int id, UmbracoEntityTypes type) + { + ActionResult foundContentResult = GetResultForId(id, type); + EntityBasic? foundContent = foundContentResult.Value; + if (foundContent is null) + { + return foundContentResult; + } + return new ActionResult>(foundContent.Path .Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Select( s => int.Parse(s, CultureInfo.InvariantCulture)));