diff --git a/src/Nikcio.UHeadless.Content/Queries/ContentQuery.cs b/src/Nikcio.UHeadless.Content/Queries/ContentQuery.cs index b058c695..24a869ec 100644 --- a/src/Nikcio.UHeadless.Content/Queries/ContentQuery.cs +++ b/src/Nikcio.UHeadless.Content/Queries/ContentQuery.cs @@ -6,6 +6,9 @@ using Nikcio.UHeadless.Content.Models; using Nikcio.UHeadless.Content.Repositories; using Nikcio.UHeadless.Content.Router; +using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Services; +using Umbraco.Extensions; namespace Nikcio.UHeadless.Content.Queries; @@ -135,4 +138,159 @@ public class ContentQuery return publishedContentType != null ? x?.GetByContentType(publishedContentType) : default; }, culture); } + + /// + /// Gets all the content items avaliable + /// + /// + /// + /// + /// + [GraphQLDescription("Gets all the content items avaliable.")] + [UsePaging] + [UseFiltering] + [UseSorting] + public virtual IEnumerable GetContentAll([Service] IContentRepository contentRepository, + [GraphQLDescription("The culture.")] string? culture = null, + [GraphQLDescription("Fetch preview values. Preview will show unpublished items.")] bool preview = false) + { + return contentRepository.GetContentList(x => + { + return x?.GetAtRoot(preview, culture).SelectMany(content => content.Descendants(culture)) + .Concat(x?.GetAtRoot(preview, culture) ?? Enumerable.Empty()); + }, culture); + } + + /// + /// Gets descendants on a content item selected by guid + /// + /// + /// + /// + /// + /// + [GraphQLDescription("Gets descendants on a content item selected by guid.")] + [UsePaging] + [UseFiltering] + [UseSorting] + public virtual IEnumerable GetContentDescendantsByGuid([Service] IContentRepository contentRepository, + [GraphQLDescription("The id to fetch.")] Guid id, + [GraphQLDescription("The culture.")] string? culture = null, + [GraphQLDescription("Fetch preview values. Preview will show unpublished items.")] bool preview = false) + { + return contentRepository.GetContentList(x => + { + return x?.GetById(preview, id)?.Descendants(culture) ?? Enumerable.Empty(); + }, culture); + } + + /// + /// Gets descendants on a content item selected by id + /// + /// + /// + /// + /// + /// + [GraphQLDescription("Gets descendants on a content item selected by id.")] + [UsePaging] + [UseFiltering] + [UseSorting] + public virtual IEnumerable GetContentDescendantsById([Service] IContentRepository contentRepository, + [GraphQLDescription("The id to fetch.")] int id, + [GraphQLDescription("The culture.")] string? culture = null, + [GraphQLDescription("Fetch preview values. Preview will show unpublished items.")] bool preview = false) + { + return contentRepository.GetContentList(x => + { + return x?.GetById(preview, id)?.Descendants(culture) ?? Enumerable.Empty(); + }, culture); + } + + /// + /// Gets all descendants of content items with a specific content type (Missing preview) + /// + /// + /// + /// + /// + [GraphQLDescription("Gets all descendants of content items with a specific content type.")] + [UsePaging] + [UseFiltering] + [UseSorting] + public virtual IEnumerable GetContentDescendantsByContentType([Service] IContentRepository contentRepository, + [GraphQLDescription("The contentType to fetch.")] string contentType, + [GraphQLDescription("The culture.")] string? culture = null) + { + + return contentRepository.GetContentList(x => + { + var publishedContentType = x?.GetContentType(contentType); + return publishedContentType != null ? x?.GetByContentType(publishedContentType).SelectMany(content => content.Descendants(culture)) : default; + }, culture); + } + + /// + /// Gets content item descendants by an absolute route + /// + /// + /// + /// + /// + /// + /// + /// + [GraphQLDescription("Gets content item descendants by an absolute route.")] + [UsePaging] + [UseFiltering] + [UseSorting] + public virtual async Task> GetContentDescendantsByAbsoluteRoute( + [Service] IContentRouter contentRouter, + [GraphQLDescription("The route to fetch. Example '/da/frontpage/'.")] string route, + [GraphQLDescription("The base url for the request. Example: 'https://localhost:4000'. Default is the current domain")] string baseUrl = "", + [GraphQLDescription("The culture.")] string? culture = null, + [GraphQLDescription("Fetch preview values. Preview will show unpublished items.")] bool preview = false, + [GraphQLDescription("Modes for requesting by route")] RouteMode routeMode = RouteMode.Routing) + { + + if (routeMode is RouteMode.Routing or RouteMode.RoutingOrCache) + { + baseUrl = contentRouter.SetBaseUrl(baseUrl); + } + + return routeMode switch + { + RouteMode.Routing => await contentRouter.GetContentDescendantsByRouting(route, baseUrl, culture), + RouteMode.RoutingOrCache => await contentRouter.GetContentDescendantsByRouting(route, baseUrl, culture) ?? contentRouter.GetContentDescendantsByRouteCache(route, culture, preview), + RouteMode.CacheOrRouting => contentRouter.GetContentDescendantsByRouteCache(route, culture, preview) ?? await contentRouter.GetContentDescendantsByRouting(route, baseUrl, culture), + RouteMode.CacheOnly => contentRouter.GetContentDescendantsByRouteCache(route, culture, preview), + _ => await contentRouter.GetContentDescendantsByRouting(route, baseUrl, culture), + }; + } + + /// + /// Gets content items by tag + /// + /// + /// + /// + /// + /// + /// + [GraphQLDescription("Gets content items by tag.")] + [UsePaging] + [UseFiltering] + [UseSorting] + public virtual IEnumerable GetContentByTag([Service] IContentRepository contentRepository, + [Service] ITagService tagService, + [GraphQLDescription("The tag to fetch.")] string tag, + [GraphQLDescription("The tag group to fetch.")] string? tagGroup = null, + [GraphQLDescription("The culture to fetch.")] string? culture = null) + { + return contentRepository.GetContentList(x => + { + var taggedEntities = tagService.GetTaggedContentByTag(tag, tagGroup, culture); + return taggedEntities.Select(entity => x?.GetById(entity.EntityId)).OfType(); + }, culture); + } } \ No newline at end of file diff --git a/src/Nikcio.UHeadless.Content/Router/ContentRouter.cs b/src/Nikcio.UHeadless.Content/Router/ContentRouter.cs index 8f62f786..e976a0b5 100644 --- a/src/Nikcio.UHeadless.Content/Router/ContentRouter.cs +++ b/src/Nikcio.UHeadless.Content/Router/ContentRouter.cs @@ -3,7 +3,9 @@ using Nikcio.UHeadless.Content.Commands; using Nikcio.UHeadless.Content.Models; using Nikcio.UHeadless.Content.Repositories; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Routing; +using Umbraco.Extensions; namespace Nikcio.UHeadless.Content.Router; @@ -110,4 +112,24 @@ public virtual string SetBaseUrl(string baseUrl) return contentRepository.GetContent(x => x?.GetByRoute(preview, route, culture: culture), culture); } + /// + public IEnumerable GetContentDescendantsByRouteCache(string route, string? culture, bool preview) + { + return contentRepository.GetContentList(x => x?.GetByRoute(preview, route, culture: culture)?.Descendants(culture) ?? Enumerable.Empty(), culture); + } + + /// + public async Task> GetContentDescendantsByRouting(string route, string baseUrl, string? culture) + { + var builder = await publishedRouter.CreateRequestAsync(new Uri($"{baseUrl}{route}")); + var request = await publishedRouter.RouteRequestAsync(builder, new RouteRequestOptions(RouteDirection.Inbound)); + + return request.GetRouteResult() switch + { + UmbracoRouteResult.Redirect => GetRedirect(request).AsEnumerableOfOne() ?? Enumerable.Empty(), + UmbracoRouteResult.NotFound => default, + UmbracoRouteResult.Success => request.PublishedContent != null ? request.PublishedContent.Descendants(culture).Select(content => contentRepository.GetConvertedContent(content, culture)) : Enumerable.Empty(), + _ => default, + }; + } } diff --git a/src/Nikcio.UHeadless.Content/Router/IContentRouter.cs b/src/Nikcio.UHeadless.Content/Router/IContentRouter.cs index ce560141..5c9a84b9 100644 --- a/src/Nikcio.UHeadless.Content/Router/IContentRouter.cs +++ b/src/Nikcio.UHeadless.Content/Router/IContentRouter.cs @@ -34,6 +34,24 @@ public interface IContentRouter /// Task GetContentByRouting(string route, string baseUrl, string? culture); + /// + /// Gets content descendants by cache + /// + /// + /// + /// + /// + IEnumerable GetContentDescendantsByRouteCache(string route, string? culture, bool preview); + + /// + /// Gets content descendants by routing + /// + /// + /// + /// + /// + Task> GetContentDescendantsByRouting(string route, string baseUrl, string? culture); + /// /// Gets a content redirect result /// diff --git a/test/v10/uSync/v9/ContentTypes/default.config b/test/v10/uSync/v9/ContentTypes/default.config index 8bf4b220..5ccc55cf 100644 --- a/test/v10/uSync/v9/ContentTypes/default.config +++ b/test/v10/uSync/v9/ContentTypes/default.config @@ -24,6 +24,31 @@ default - - + + + 46d16fdd-6f68-4483-849a-6ae7c877521f + tageditor + tageditor + b6b73142-b9c1-4bf8-a16d-e1c23320b549 + Umbraco.Tags + false + + + 0 + Content + Nothing + + + false + + + + + 07d1ae3b-64f7-4a29-8ebf-6201a7239c67 + Content + content + Tab + 0 + + \ No newline at end of file