diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/SearchDocumentItemController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/SearchDocumentItemController.cs index 415fd156d4..f3b7cb1caf 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/SearchDocumentItemController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/SearchDocumentItemController.cs @@ -21,16 +21,21 @@ public class SearchDocumentItemController : DocumentItemControllerBase _documentPresentationFactory = documentPresentationFactory; } + [NonAction] + [Obsolete("Scheduled to be removed in v16, use the non obsoleted method instead")] + public async Task Search(CancellationToken cancellationToken, string query, int skip = 0, int take = 100) + => await SearchFromParent(cancellationToken, query, skip, take); + [HttpGet("search")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedModel), StatusCodes.Status200OK)] - public async Task Search(CancellationToken cancellationToken, string query, int skip = 0, int take = 100) + public async Task SearchFromParent(CancellationToken cancellationToken, string query, int skip = 0, int take = 100, Guid? parentId = null) { - PagedModel searchResult = _indexedEntitySearchService.Search(UmbracoObjectTypes.Document, query, skip, take); + PagedModel searchResult = _indexedEntitySearchService.Search(UmbracoObjectTypes.Document, query, parentId, skip, take); var result = new PagedModel { Items = searchResult.Items.OfType().Select(_documentPresentationFactory.CreateItemResponseModel), - Total = searchResult.Total + Total = searchResult.Total, }; return await Task.FromResult(Ok(result)); diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/SearchMediaItemController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/SearchMediaItemController.cs index 37543444fb..81d4f17748 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/SearchMediaItemController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/SearchMediaItemController.cs @@ -21,16 +21,21 @@ public class SearchMediaItemController : MediaItemControllerBase _mediaPresentationFactory = mediaPresentationFactory; } + [NonAction] + [Obsolete("Scheduled to be removed in v16, use the non obsoleted method instead")] + public async Task Search(CancellationToken cancellationToken, string query, int skip = 0, int take = 100) + => await SearchFromParent(cancellationToken, query, skip, take, null); + [HttpGet("search")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedModel), StatusCodes.Status200OK)] - public async Task Search(CancellationToken cancellationToken, string query, int skip = 0, int take = 100) + public async Task SearchFromParent(CancellationToken cancellationToken, string query, int skip = 0, int take = 100, Guid? parentId = null) { - PagedModel searchResult = _indexedEntitySearchService.Search(UmbracoObjectTypes.Media, query, skip, take); + PagedModel searchResult = _indexedEntitySearchService.Search(UmbracoObjectTypes.Media, query, parentId, skip, take); var result = new PagedModel { Items = searchResult.Items.OfType().Select(_mediaPresentationFactory.CreateItemResponseModel), - Total = searchResult.Total + Total = searchResult.Total, }; return await Task.FromResult(Ok(result)); diff --git a/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs b/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs index 047f5e7e2f..4463733146 100644 --- a/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs +++ b/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs @@ -13,4 +13,8 @@ namespace Umbraco.Cms.Core.Services; public interface IIndexedEntitySearchService { PagedModel Search(UmbracoObjectTypes objectType, string query, int skip = 0, int take = 100, bool ignoreUserStartNodes = false); + + // default implementation to avoid breaking changes falls back to old behaviour + PagedModel Search(UmbracoObjectTypes objectType, string query, Guid? parentId, int skip = 0, int take = 100, bool ignoreUserStartNodes = false) + => Search(objectType,query, skip, take, ignoreUserStartNodes); } diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs index 43c542faa0..7f78b07a1a 100644 --- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs +++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs @@ -356,8 +356,16 @@ public class BackOfficeExamineSearcher : IBackOfficeExamineSearcher throw new ArgumentNullException(nameof(entityService)); } - UdiParser.TryParse(searchFrom, true, out Udi? udi); - searchFrom = udi == null ? searchFrom : entityService.GetId(udi).Result.ToString(); + if (Guid.TryParse(searchFrom, out Guid guid)) + { + searchFrom = entityService.GetId(guid, objectType).Result.ToString(); + } + else + { + // fallback to Udi for legacy reasons as the calling methods take string? + UdiParser.TryParse(searchFrom, true, out Udi? udi); + searchFrom = udi == null ? searchFrom : entityService.GetId(udi).Result.ToString(); + } TreeEntityPath? entityPath = int.TryParse(searchFrom, NumberStyles.Integer, CultureInfo.InvariantCulture, out var searchFromId) && diff --git a/src/Umbraco.Infrastructure/Services/Implement/IndexedEntitySearchService.cs b/src/Umbraco.Infrastructure/Services/Implement/IndexedEntitySearchService.cs index 0055df6244..0f097df262 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/IndexedEntitySearchService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/IndexedEntitySearchService.cs @@ -20,6 +20,15 @@ internal sealed class IndexedEntitySearchService : IIndexedEntitySearchService } public PagedModel Search(UmbracoObjectTypes objectType, string query, int skip = 0, int take = 100, bool ignoreUserStartNodes = false) + => Search(objectType, query, null, skip, take, ignoreUserStartNodes); + + public PagedModel Search( + UmbracoObjectTypes objectType, + string query, + Guid? parentId, + int skip = 0, + int take = 100, + bool ignoreUserStartNodes = false) { UmbracoEntityTypes entityType = objectType switch { @@ -37,7 +46,8 @@ internal sealed class IndexedEntitySearchService : IIndexedEntitySearchService pageSize, pageNumber, out var totalFound, - ignoreUserStartNodes: ignoreUserStartNodes); + ignoreUserStartNodes: ignoreUserStartNodes, + searchFrom: parentId?.ToString()); Guid[] keys = searchResults.Select( result => diff --git a/src/Umbraco.Web.UI.Login/src/controllers/slim-backoffice-initializer.ts b/src/Umbraco.Web.UI.Login/src/controllers/slim-backoffice-initializer.ts index 45422bf272..681ab098a7 100644 --- a/src/Umbraco.Web.UI.Login/src/controllers/slim-backoffice-initializer.ts +++ b/src/Umbraco.Web.UI.Login/src/controllers/slim-backoffice-initializer.ts @@ -2,7 +2,10 @@ import { UmbBundleExtensionInitializer, UmbServerExtensionRegistrator } from "@umbraco-cms/backoffice/extension-api"; -import { umbExtensionsRegistry } from "@umbraco-cms/backoffice/extension-registry"; +import { + UmbAppEntryPointExtensionInitializer, + umbExtensionsRegistry +} from "@umbraco-cms/backoffice/extension-registry"; import type { UmbElement } from "@umbraco-cms/backoffice/element-api"; import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api"; import { UUIIconRegistryEssential } from "@umbraco-cms/backoffice/external/uui"; @@ -21,6 +24,7 @@ export class UmbSlimBackofficeController extends UmbControllerBase { constructor(host: UmbElement) { super(host); new UmbBundleExtensionInitializer(host, umbExtensionsRegistry); + new UmbAppEntryPointExtensionInitializer(host, umbExtensionsRegistry); new UmbServerExtensionRegistrator(host, umbExtensionsRegistry).registerPublicExtensions(); this.#uuiIconRegistry.attach(host);