diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Composition/AvailableCompositionController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Composition/AvailableCompositionController.cs new file mode 100644 index 0000000000..769f856f24 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Composition/AvailableCompositionController.cs @@ -0,0 +1,38 @@ +using Asp.Versioning; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Services.ContentTypeEditing; + +namespace Umbraco.Cms.Api.Management.Controllers.DocumentType.Composition; + +[ApiVersion("1.0")] +public class AvailableCompositionController : DocumentTypeControllerBase +{ + private readonly IContentTypeEditingService _contentTypeEditingService; + private readonly IDocumentTypeEditingPresentationFactory _presentationFactory; + + public AvailableCompositionController(IContentTypeEditingService contentTypeEditingService, IDocumentTypeEditingPresentationFactory presentationFactory) + { + _contentTypeEditingService = contentTypeEditingService; + _presentationFactory = presentationFactory; + } + + [HttpPost("available-compositions")] + [MapToApiVersion("1.0")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task AvailableCompositions(DocumentTypeCompositionRequestModel compositionModel) + { + IEnumerable availableCompositions = await _contentTypeEditingService.GetAvailableCompositionsAsync( + compositionModel.Id, + compositionModel.CurrentCompositeIds, + compositionModel.CurrentPropertyAliases, + compositionModel.IsElement); + + IEnumerable responseModels = _presentationFactory.MapCompositionModels(availableCompositions); + + return Ok(responseModels); + } +} diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Composition/ReferencesCompositionController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Composition/ReferencesCompositionController.cs new file mode 100644 index 0000000000..cdf5b1e32b --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Composition/ReferencesCompositionController.cs @@ -0,0 +1,43 @@ +using Asp.Versioning; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; +using Umbraco.Cms.Core.Mapping; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services.OperationStatus; + +namespace Umbraco.Cms.Api.Management.Controllers.DocumentType.Composition; + +[ApiVersion("1.0")] +public class ReferencesCompositionController : DocumentTypeControllerBase +{ + private readonly IContentTypeService _contentTypeService; + private readonly IUmbracoMapper _umbracoMapper; + + public ReferencesCompositionController(IContentTypeService contentTypeService, IUmbracoMapper umbracoMapper) + { + _contentTypeService = contentTypeService; + _umbracoMapper = umbracoMapper; + } + + [HttpGet("{id:guid}/composition-references")] + [MapToApiVersion("1.0")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + public async Task CompositionReferences(Guid id) + { + var contentType = await _contentTypeService.GetAsync(id); + + if (contentType is null) + { + return OperationStatusResult(ContentTypeOperationStatus.NotFound); + } + + IEnumerable composedOf = _contentTypeService.GetComposedOf(contentType.Id); + List responseModels = _umbracoMapper.MapEnumerable(composedOf); + + return Ok(responseModels); + } +} diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Composition/AvailableCompositionController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Composition/AvailableCompositionController.cs new file mode 100644 index 0000000000..05c9c25a9a --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Composition/AvailableCompositionController.cs @@ -0,0 +1,37 @@ +using Asp.Versioning; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Services.ContentTypeEditing; + +namespace Umbraco.Cms.Api.Management.Controllers.MediaType.Composition; + +[ApiVersion("1.0")] +public class AvailableCompositionController : MediaTypeControllerBase +{ + private readonly IMediaTypeEditingService _mediaTypeEditingService; + private readonly IMediaTypeEditingPresentationFactory _presentationFactory; + + public AvailableCompositionController(IMediaTypeEditingService mediaTypeEditingService, IMediaTypeEditingPresentationFactory presentationFactory) + { + _mediaTypeEditingService = mediaTypeEditingService; + _presentationFactory = presentationFactory; + } + + [HttpPost("available-compositions")] + [MapToApiVersion("1.0")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task AvailableCompositions(MediaTypeCompositionRequestModel compositionModel) + { + IEnumerable availableCompositions = await _mediaTypeEditingService.GetAvailableCompositionsAsync( + compositionModel.Id, + compositionModel.CurrentCompositeIds, + compositionModel.CurrentPropertyAliases); + + IEnumerable responseModels = _presentationFactory.MapCompositionModels(availableCompositions); + + return Ok(responseModels); + } +} diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Composition/ReferencesCompositionController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Composition/ReferencesCompositionController.cs new file mode 100644 index 0000000000..374e8862ed --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Composition/ReferencesCompositionController.cs @@ -0,0 +1,43 @@ +using Asp.Versioning; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; +using Umbraco.Cms.Core.Mapping; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services.OperationStatus; + +namespace Umbraco.Cms.Api.Management.Controllers.MediaType.Composition; + +[ApiVersion("1.0")] +public class ReferencesCompositionController : MediaTypeControllerBase +{ + private readonly IMediaTypeService _mediaTypeService; + private readonly IUmbracoMapper _umbracoMapper; + + public ReferencesCompositionController(IMediaTypeService mediaTypeService, IUmbracoMapper umbracoMapper) + { + _mediaTypeService = mediaTypeService; + _umbracoMapper = umbracoMapper; + } + + [HttpGet("{id:guid}/composition-references")] + [MapToApiVersion("1.0")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + public async Task CompositionReferences(Guid id) + { + var mediaType = await _mediaTypeService.GetAsync(id); + + if (mediaType is null) + { + return OperationStatusResult(ContentTypeOperationStatus.NotFound); + } + + IEnumerable composedOf = _mediaTypeService.GetComposedOf(mediaType.Id); + List responseModels = _umbracoMapper.MapEnumerable(composedOf); + + return Ok(responseModels); + } +} diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentTypeBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentTypeBuilderExtensions.cs index 8acab3feb2..596676bc19 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentTypeBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentTypeBuilderExtensions.cs @@ -13,6 +13,7 @@ internal static class DocumentTypeBuilderExtensions builder.Services.AddTransient(); builder.WithCollectionBuilder().Add(); + builder.WithCollectionBuilder().Add(); return builder; } diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaTypeBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaTypeBuilderExtensions.cs index f38e385858..3c74fa85d8 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaTypeBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaTypeBuilderExtensions.cs @@ -13,6 +13,7 @@ internal static class MediaTypeBuilderExtensions builder.Services.AddTransient(); builder.WithCollectionBuilder().Add(); + builder.WithCollectionBuilder().Add(); return builder; } diff --git a/src/Umbraco.Cms.Api.Management/Factories/ContentTypeEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/ContentTypeEditingPresentationFactory.cs index 621643d27f..a5a381ca0c 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/ContentTypeEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/ContentTypeEditingPresentationFactory.cs @@ -6,11 +6,12 @@ using ContentTypeViewModels = Umbraco.Cms.Api.Management.ViewModels.ContentType; namespace Umbraco.Cms.Api.Management.Factories; -internal abstract class ContentTypeEditingPresentationFactory +internal abstract class ContentTypeEditingPresentationFactory + where TContentType : IContentTypeComposition { - private readonly IContentTypeService _contentTypeService; + private readonly IContentTypeBaseService _contentTypeService; - protected ContentTypeEditingPresentationFactory(IContentTypeService contentTypeService) + protected ContentTypeEditingPresentationFactory(IContentTypeBaseService contentTypeService) => _contentTypeService = contentTypeService; protected TContentTypeEditingModel MapContentTypeEditingModel< @@ -45,6 +46,30 @@ internal abstract class ContentTypeEditingPresentationFactory return editingModel; } + protected T MapCompositionModel(ContentTypeAvailableCompositionsResult compositionResult) + where T : ContentTypeViewModels.AvailableContentTypeCompositionResponseModelBase, new() + { + IContentTypeComposition composition = compositionResult.Composition; + IEnumerable? folders = null; + + if (composition is TContentType contentType) + { + var containers = _contentTypeService.GetContainers(contentType); + folders = containers.Select(c => c.Name).WhereNotNull(); + } + + T compositionModel = new() + { + Id = composition.Key, + Name = composition.Name ?? string.Empty, + Icon = composition.Icon ?? string.Empty, + FolderPath = folders ?? Array.Empty(), + IsCompatible = compositionResult.Allowed + }; + + return compositionModel; + } + private ContentTypeSort[] MapAllowedContentTypes(IEnumerable allowedContentTypes) { // need to fetch the content type aliases to construct the corresponding ContentTypeSort entities diff --git a/src/Umbraco.Cms.Api.Management/Factories/DocumentTypeEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/DocumentTypeEditingPresentationFactory.cs index 246da2f5a7..d11be5185e 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/DocumentTypeEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/DocumentTypeEditingPresentationFactory.cs @@ -1,11 +1,13 @@ using Umbraco.Cms.Api.Management.ViewModels.DocumentType; +using Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Core.Services; using ContentTypeCleanupViewModel = Umbraco.Cms.Api.Management.ViewModels.ContentType.ContentTypeCleanup; namespace Umbraco.Cms.Api.Management.Factories; -internal sealed class DocumentTypeEditingPresentationFactory : ContentTypeEditingPresentationFactory, IDocumentTypeEditingPresentationFactory +internal sealed class DocumentTypeEditingPresentationFactory : ContentTypeEditingPresentationFactory, IDocumentTypeEditingPresentationFactory { public DocumentTypeEditingPresentationFactory(IContentTypeService contentTypeService) : base(contentTypeService) @@ -50,6 +52,9 @@ internal sealed class DocumentTypeEditingPresentationFactory : ContentTypeEditin return updateModel; } + public IEnumerable MapCompositionModels(IEnumerable compositionResults) + => compositionResults.Select(MapCompositionModel); + private void MapCleanup(ContentTypeModelBase model, ContentTypeCleanupViewModel cleanup) => model.Cleanup = new ContentTypeCleanup { diff --git a/src/Umbraco.Cms.Api.Management/Factories/IDocumentTypeEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IDocumentTypeEditingPresentationFactory.cs index 1a45056aea..4b6d3967fc 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/IDocumentTypeEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/IDocumentTypeEditingPresentationFactory.cs @@ -1,4 +1,6 @@ using Umbraco.Cms.Api.Management.ViewModels.DocumentType; +using Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; namespace Umbraco.Cms.Api.Management.Factories; @@ -8,4 +10,6 @@ public interface IDocumentTypeEditingPresentationFactory ContentTypeCreateModel MapCreateModel(CreateDocumentTypeRequestModel requestModel); ContentTypeUpdateModel MapUpdateModel(UpdateDocumentTypeRequestModel requestModel); + + IEnumerable MapCompositionModels(IEnumerable compositionResults); } diff --git a/src/Umbraco.Cms.Api.Management/Factories/IMediaTypeEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IMediaTypeEditingPresentationFactory.cs index 3e817fa448..8dc4352e35 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/IMediaTypeEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/IMediaTypeEditingPresentationFactory.cs @@ -1,4 +1,6 @@ using Umbraco.Cms.Api.Management.ViewModels.MediaType; +using Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; namespace Umbraco.Cms.Api.Management.Factories; @@ -8,4 +10,6 @@ public interface IMediaTypeEditingPresentationFactory MediaTypeCreateModel MapCreateModel(CreateMediaTypeRequestModel requestModel); MediaTypeUpdateModel MapUpdateModel(UpdateMediaTypeRequestModel requestModel); + + IEnumerable MapCompositionModels(IEnumerable compositionResults); } diff --git a/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs index 93d0629a73..f0bffc1858 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/MediaTypeEditingPresentationFactory.cs @@ -1,13 +1,15 @@ using Umbraco.Cms.Api.Management.ViewModels.MediaType; +using Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Api.Management.Factories; -internal sealed class MediaTypeEditingPresentationFactory : ContentTypeEditingPresentationFactory, IMediaTypeEditingPresentationFactory +internal sealed class MediaTypeEditingPresentationFactory : ContentTypeEditingPresentationFactory, IMediaTypeEditingPresentationFactory { - public MediaTypeEditingPresentationFactory(IContentTypeService contentTypeService) - : base(contentTypeService) + public MediaTypeEditingPresentationFactory(IMediaTypeService mediaTypeService) + : base(mediaTypeService) { } @@ -22,7 +24,7 @@ internal sealed class MediaTypeEditingPresentationFactory : ContentTypeEditingPr >(requestModel); createModel.Key = requestModel.Id; - createModel.ParentKey = requestModel.ContainerId; + createModel.ContainerKey = requestModel.ContainerId; return createModel; } @@ -35,4 +37,7 @@ internal sealed class MediaTypeEditingPresentationFactory : ContentTypeEditingPr UpdateMediaTypePropertyTypeRequestModel, UpdateMediaTypePropertyTypeContainerRequestModel >(requestModel); + + public IEnumerable MapCompositionModels(IEnumerable compositionResults) + => compositionResults.Select(MapCompositionModel); } diff --git a/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeCompositionMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeCompositionMapDefinition.cs new file mode 100644 index 0000000000..5c0852b9ee --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeCompositionMapDefinition.cs @@ -0,0 +1,20 @@ +using Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; +using Umbraco.Cms.Core.Mapping; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Api.Management.Mapping.DocumentType; + +public class DocumentTypeCompositionMapDefinition : IMapDefinition +{ + public void DefineMaps(IUmbracoMapper mapper) + => mapper.Define( + (_, _) => new DocumentTypeCompositionResponseModel(), Map); + + // Umbraco.Code.MapAll + private static void Map(IContentType source, DocumentTypeCompositionResponseModel target, MapperContext context) + { + target.Id = source.Key; + target.Name = source.Name ?? string.Empty; + target.Icon = source.Icon ?? string.Empty; + } +} diff --git a/src/Umbraco.Cms.Api.Management/Mapping/MediaType/MediaTypeCompositionMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/MediaType/MediaTypeCompositionMapDefinition.cs new file mode 100644 index 0000000000..7052e88cd4 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Mapping/MediaType/MediaTypeCompositionMapDefinition.cs @@ -0,0 +1,20 @@ +using Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; +using Umbraco.Cms.Core.Mapping; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Api.Management.Mapping.MediaType; + +public class MediaTypeCompositionMapDefinition : IMapDefinition +{ + public void DefineMaps(IUmbracoMapper mapper) + => mapper.Define( + (_, _) => new MediaTypeCompositionResponseModel(), Map); + + // Umbraco.Code.MapAll + private static void Map(IContentType source, MediaTypeCompositionResponseModel target, MapperContext context) + { + target.Id = source.Key; + target.Name = source.Name ?? string.Empty; + target.Icon = source.Icon ?? string.Empty; + } +} diff --git a/src/Umbraco.Cms.Api.Management/OpenApi.json b/src/Umbraco.Cms.Api.Management/OpenApi.json index f6f12cb1da..5b204be532 100644 --- a/src/Umbraco.Cms.Api.Management/OpenApi.json +++ b/src/Umbraco.Cms.Api.Management/OpenApi.json @@ -2986,6 +2986,116 @@ ] } }, + "/umbraco/management/api/v1/document-type/{id}/composition-references": { + "get": { + "tags": [ + "Document Type" + ], + "operationId": "GetDocumentTypeByIdCompositionReferences", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/DocumentTypeCompositionResponseModel" + } + ] + } + } + }, + "text/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/DocumentTypeCompositionResponseModel" + } + ] + } + } + }, + "text/plain": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/DocumentTypeCompositionResponseModel" + } + ] + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "401": { + "description": "The resource is protected and requires an authentication token" + } + }, + "security": [ + { + "Backoffice User": [ ] + } + ] + } + }, "/umbraco/management/api/v1/document-type/{id}/copy": { "post": { "tags": [ @@ -3202,6 +3312,96 @@ ] } }, + "/umbraco/management/api/v1/document-type/available-compositions": { + "post": { + "tags": [ + "Document Type" + ], + "operationId": "PostDocumentTypeAvailableCompositions", + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/DocumentTypeCompositionRequestModel" + } + ] + } + }, + "text/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/DocumentTypeCompositionRequestModel" + } + ] + } + }, + "application/*+json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/DocumentTypeCompositionRequestModel" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/AvailableDocumentTypeCompositionResponseModel" + } + ] + } + } + }, + "text/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/AvailableDocumentTypeCompositionResponseModel" + } + ] + } + } + }, + "text/plain": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/AvailableDocumentTypeCompositionResponseModel" + } + ] + } + } + } + } + }, + "401": { + "description": "The resource is protected and requires an authentication token" + } + }, + "security": [ + { + "Backoffice User": [ ] + } + ] + } + }, "/umbraco/management/api/v1/document-type/folder": { "post": { "tags": [ @@ -8252,6 +8452,116 @@ ] } }, + "/umbraco/management/api/v1/media-type/{id}/composition-references": { + "get": { + "tags": [ + "Media Type" + ], + "operationId": "GetMediaTypeByIdCompositionReferences", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/MediaTypeCompositionResponseModel" + } + ] + } + } + }, + "text/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/MediaTypeCompositionResponseModel" + } + ] + } + } + }, + "text/plain": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/MediaTypeCompositionResponseModel" + } + ] + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + }, + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "401": { + "description": "The resource is protected and requires an authentication token" + } + }, + "security": [ + { + "Backoffice User": [ ] + } + ] + } + }, "/umbraco/management/api/v1/media-type/{id}/copy": { "post": { "tags": [ @@ -8468,6 +8778,96 @@ ] } }, + "/umbraco/management/api/v1/media-type/available-compositions": { + "post": { + "tags": [ + "Media Type" + ], + "operationId": "PostMediaTypeAvailableCompositions", + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/MediaTypeCompositionRequestModel" + } + ] + } + }, + "text/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/MediaTypeCompositionRequestModel" + } + ] + } + }, + "application/*+json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/MediaTypeCompositionRequestModel" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/AvailableMediaTypeCompositionResponseModel" + } + ] + } + } + }, + "text/json": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/AvailableMediaTypeCompositionResponseModel" + } + ] + } + } + }, + "text/plain": { + "schema": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/AvailableMediaTypeCompositionResponseModel" + } + ] + } + } + } + } + }, + "401": { + "description": "The resource is protected and requires an authentication token" + } + }, + "security": [ + { + "Backoffice User": [ ] + } + ] + } + }, "/umbraco/management/api/v1/media-type/folder": { "post": { "tags": [ @@ -19832,6 +20232,56 @@ ], "type": "string" }, + "AvailableContentTypeCompositionResponseModelBaseModel": { + "required": [ + "folderPath", + "icon", + "id", + "isCompatible", + "name" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "folderPath": { + "type": "array", + "items": { + "type": "string" + } + }, + "isCompatible": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "AvailableDocumentTypeCompositionResponseModel": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AvailableContentTypeCompositionResponseModelBaseModel" + } + ], + "additionalProperties": false + }, + "AvailableMediaTypeCompositionResponseModel": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AvailableContentTypeCompositionResponseModelBaseModel" + } + ], + "additionalProperties": false + }, "ChangePasswordUserRequestModel": { "required": [ "newPassword" @@ -19979,6 +20429,55 @@ }, "additionalProperties": false }, + "ContentTypeCompositionRequestModelBaseModel": { + "required": [ + "currentCompositeIds", + "currentPropertyAliases" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "currentPropertyAliases": { + "type": "array", + "items": { + "type": "string" + } + }, + "currentCompositeIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + } + }, + "additionalProperties": false + }, + "ContentTypeCompositionResponseModelBaseModel": { + "required": [ + "icon", + "id", + "name" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "icon": { + "type": "string" + } + }, + "additionalProperties": false + }, "ContentTypeCompositionTypeModel": { "enum": [ "Composition", @@ -21558,6 +22057,32 @@ }, "additionalProperties": false }, + "DocumentTypeCompositionRequestModel": { + "required": [ + "isElement" + ], + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ContentTypeCompositionRequestModelBaseModel" + } + ], + "properties": { + "isElement": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DocumentTypeCompositionResponseModel": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ContentTypeCompositionResponseModelBaseModel" + } + ], + "additionalProperties": false + }, "DocumentTypeItemResponseModel": { "required": [ "isElement" @@ -22734,6 +23259,24 @@ }, "additionalProperties": false }, + "MediaTypeCompositionRequestModel": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ContentTypeCompositionRequestModelBaseModel" + } + ], + "additionalProperties": false + }, + "MediaTypeCompositionResponseModel": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ContentTypeCompositionResponseModelBaseModel" + } + ], + "additionalProperties": false + }, "MediaTypeItemResponseModel": { "type": "object", "allOf": [ diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/AvailableContentTypeCompositionResponseModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/AvailableContentTypeCompositionResponseModelBase.cs new file mode 100644 index 0000000000..a409d62150 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/AvailableContentTypeCompositionResponseModelBase.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.ContentType; + +public abstract class AvailableContentTypeCompositionResponseModelBase : ContentTypeCompositionResponseModelBase +{ + /// Empty when located at root. + public IEnumerable FolderPath { get; set; } = Array.Empty(); + + public bool IsCompatible { get; set; } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCompositionRequestModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCompositionRequestModelBase.cs new file mode 100644 index 0000000000..3402024284 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCompositionRequestModelBase.cs @@ -0,0 +1,27 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.ContentType; + +public abstract class ContentTypeCompositionRequestModelBase +{ + /// + /// Gets or sets the content type key. + /// + public Guid? Id { get; set; } + + /// + /// Gets or sets the currently selected property aliases. + /// + /// + /// This is required because when creating/modifying a content type, new properties being added to + /// it are not yet persisted so cannot be looked up via the db, they need to be passed in. + /// + public IEnumerable CurrentPropertyAliases { get; set; } = Array.Empty(); + + /// + /// Gets or sets the keys of the currently selected content types for composition (also direct inheritance). + /// + /// + /// Any content types containing those aliases will be filtered out along with any content types + /// that have matching property types that are included in the specified ones. + /// + public IEnumerable CurrentCompositeIds { get; set; } = Array.Empty(); +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCompositionResponseModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCompositionResponseModelBase.cs new file mode 100644 index 0000000000..38a0bf70d3 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCompositionResponseModelBase.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.ContentType; + +public abstract class ContentTypeCompositionResponseModelBase +{ + public Guid Id { get; set; } + + public string Name { get; set; } = string.Empty; + + public string Icon { get; set; } = string.Empty; +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/AvailableDocumentTypeCompositionResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/AvailableDocumentTypeCompositionResponseModel.cs new file mode 100644 index 0000000000..83569fa4a2 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/AvailableDocumentTypeCompositionResponseModel.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Api.Management.ViewModels.ContentType; + +namespace Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; + +public class AvailableDocumentTypeCompositionResponseModel : AvailableContentTypeCompositionResponseModelBase +{ +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/DocumentTypeCompositionRequestModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/DocumentTypeCompositionRequestModel.cs new file mode 100644 index 0000000000..ca9cdf1c28 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/DocumentTypeCompositionRequestModel.cs @@ -0,0 +1,11 @@ +using Umbraco.Cms.Api.Management.ViewModels.ContentType; + +namespace Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; + +public class DocumentTypeCompositionRequestModel : ContentTypeCompositionRequestModelBase +{ + /// + /// Gets or sets a value indicating whether the content type is currently marked as an element type. + /// + public bool IsElement { get; set; } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/DocumentTypeCompositionResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/DocumentTypeCompositionResponseModel.cs new file mode 100644 index 0000000000..ff241da622 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/DocumentType/Composition/DocumentTypeCompositionResponseModel.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Api.Management.ViewModels.ContentType; + +namespace Umbraco.Cms.Api.Management.ViewModels.DocumentType.Composition; + +public class DocumentTypeCompositionResponseModel : ContentTypeCompositionResponseModelBase +{ +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/AvailableMediaTypeCompositionResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/AvailableMediaTypeCompositionResponseModel.cs new file mode 100644 index 0000000000..21cae2a15e --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/AvailableMediaTypeCompositionResponseModel.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Api.Management.ViewModels.ContentType; + +namespace Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; + +public class AvailableMediaTypeCompositionResponseModel : AvailableContentTypeCompositionResponseModelBase +{ +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/MediaTypeCompositionRequestModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/MediaTypeCompositionRequestModel.cs new file mode 100644 index 0000000000..3f6d06b6b4 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/MediaTypeCompositionRequestModel.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Api.Management.ViewModels.ContentType; + +namespace Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; + +public class MediaTypeCompositionRequestModel : ContentTypeCompositionRequestModelBase +{ +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/MediaTypeCompositionResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/MediaTypeCompositionResponseModel.cs new file mode 100644 index 0000000000..bd62815be1 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/MediaType/Composition/MediaTypeCompositionResponseModel.cs @@ -0,0 +1,7 @@ +using Umbraco.Cms.Api.Management.ViewModels.ContentType; + +namespace Umbraco.Cms.Api.Management.ViewModels.MediaType.Composition; + +public class MediaTypeCompositionResponseModel : ContentTypeCompositionResponseModelBase +{ +} diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs index 0d8583e6b3..fb69d520df 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs @@ -4,5 +4,5 @@ public class MediaTypeCreateModel : MediaTypeModelBase { public Guid? Key { get; set; } - public Guid? ParentKey { get; set; } + public Guid? ContainerKey { get; set; } } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs index d368f58285..f366a75124 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs @@ -63,6 +63,13 @@ internal sealed class ContentTypeEditingService : ContentTypeEditingServiceBase< return Attempt.SucceedWithStatus(ContentTypeOperationStatus.Success, contentType); } + public async Task> GetAvailableCompositionsAsync( + Guid? key, + IEnumerable currentCompositeKeys, + IEnumerable currentPropertyAliases, + bool isElement) => + await FindAvailableCompositionsAsync(key, currentCompositeKeys, currentPropertyAliases, isElement); + // update content type history clean-up private void UpdateHistoryCleanup(IContentType contentType, ContentTypeModelBase model) { @@ -89,13 +96,6 @@ internal sealed class ContentTypeEditingService : ContentTypeEditingServiceBase< private async Task SaveAsync(IContentType contentType, Guid userKey) => await _contentTypeService.SaveAsync(contentType, userKey); - protected override Guid[] GetAvailableCompositionKeys(IContentTypeComposition? source, IContentTypeComposition[] allContentTypes, bool isElement) - => _contentTypeService.GetAvailableCompositeContentTypes(source, allContentTypes, isElement: isElement) - .Results - .Where(x => x.Allowed) - .Select(x => x.Composition.Key) - .ToArray(); - protected override IContentType CreateContentType(IShortStringHelper shortStringHelper, int parentId) => new ContentType(shortStringHelper, parentId); diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs index ee20af2256..4fd0e98142 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs @@ -33,8 +33,6 @@ internal abstract class ContentTypeEditingServiceBase> FindAvailableCompositionsAsync( + Guid? key, + IEnumerable currentCompositeKeys, + IEnumerable currentPropertyAliases, + bool isElement = false) + { + TContentType? contentType = key.HasValue ? await _concreteContentTypeService.GetAsync(key.Value) : null; + IContentTypeComposition[] allContentTypes = _concreteContentTypeService.GetAll().ToArray(); + + var currentCompositionAliases = currentCompositeKeys.Any() + ? allContentTypes.Where(ct => currentCompositeKeys.Contains(ct.Key)).Select(ct => ct.Alias).ToArray() + : Array.Empty(); + + ContentTypeAvailableCompositionsResults availableCompositions = _contentTypeService.GetAvailableCompositeContentTypes( + contentType, + allContentTypes, + currentCompositionAliases, + currentPropertyAliases.ToArray(), + isElement); + + return availableCompositions.Results; + } + protected async Task> ValidateAndMapForCreationAsync(ContentTypeEditingModelBase model, Guid? key, Guid? containerKey) { SanitizeModelAliases(model); @@ -287,7 +308,12 @@ internal abstract class ContentTypeEditingServiceBase x.Allowed) + .Select(x => x.Composition.Key) + .ToArray(); + if (allowedCompositionKeys.ContainsAll(compositionKeys) is false) { return ContentTypeOperationStatus.InvalidComposition; diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs index 9494f99527..672bc00f7a 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs @@ -9,4 +9,10 @@ public interface IContentTypeEditingService Task> CreateAsync(ContentTypeCreateModel model, Guid userKey); Task> UpdateAsync(IContentType contentType, ContentTypeUpdateModel model, Guid userKey); + + Task> GetAvailableCompositionsAsync( + Guid? key, + IEnumerable currentCompositeKeys, + IEnumerable currentPropertyAliases, + bool isElement); } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs index b2b43814a5..0da08c7ae9 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs @@ -9,4 +9,9 @@ public interface IMediaTypeEditingService Task> CreateAsync(MediaTypeCreateModel model, Guid userKey); Task> UpdateAsync(IMediaType mediaType, MediaTypeUpdateModel model, Guid userKey); + + Task> GetAvailableCompositionsAsync( + Guid? key, + IEnumerable currentCompositeKeys, + IEnumerable currentPropertyAliases); } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs index edf9afe8a9..1eab38c69a 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs @@ -20,7 +20,7 @@ internal sealed class MediaTypeEditingService : ContentTypeEditingServiceBase> CreateAsync(MediaTypeCreateModel model, Guid userKey) { - Attempt result = await ValidateAndMapForCreationAsync(model, model.Key, model.ParentKey); + Attempt result = await ValidateAndMapForCreationAsync(model, model.Key, model.ContainerKey); if (result.Success) { IMediaType mediaType = result.Result ?? throw new InvalidOperationException($"{nameof(ValidateAndMapForCreationAsync)} succeeded but did not yield any result"); @@ -42,8 +42,11 @@ internal sealed class MediaTypeEditingService : ContentTypeEditingServiceBase Array.Empty(); + public async Task> GetAvailableCompositionsAsync( + Guid? key, + IEnumerable currentCompositeKeys, + IEnumerable currentPropertyAliases) => + await FindAvailableCompositionsAsync(key, currentCompositeKeys, currentPropertyAliases); protected override IMediaType CreateContentType(IShortStringHelper shortStringHelper, int parentId) => new MediaType(shortStringHelper, parentId); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Create.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Create.cs index 94f80d497a..28dd1f5b0b 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Create.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Create.cs @@ -13,7 +13,7 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Create_With_All_Basic_Settings(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); createModel.Description = "This is the Test description"; createModel.Icon = "icon icon-something"; createModel.AllowedAsRoot = true; @@ -41,7 +41,7 @@ public partial class ContentTypeEditingServiceTests [TestCase(true, true)] public async Task Can_Create_With_Variation(bool variesByCulture, bool variesBySegment) { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.VariesByCulture = variesByCulture; createModel.VariesBySegment = variesBySegment; @@ -65,7 +65,7 @@ public partial class ContentTypeEditingServiceTests var container = containerResult.Result?.Entity; Assert.IsNotNull(container); - var createModel = CreateCreateModel("Test", "test", isElement: isElement, parentKey: container.Key); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement, containerKey: container.Key); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsTrue(result.Success); @@ -80,11 +80,11 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Create_With_Properties_In_A_Container(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container = CreateContainer(); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container = ContentTypePropertyContainerModel(); createModel.Containers = new[] { container }; - var propertyType = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty", containerKey: container.Key); createModel.Properties = new[] { propertyType }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -107,9 +107,9 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Create_With_Orphaned_Properties(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); - var propertyType = CreatePropertyType("Test Property", "testProperty"); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty"); createModel.Properties = new[] { propertyType }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -131,7 +131,7 @@ public partial class ContentTypeEditingServiceTests public async Task Can_Specify_Key() { var key = new Guid("33C326F6-CB5E-43D6-9730-E946AA5F9C7B"); - var createModel = CreateCreateModel(key: key); + var createModel = ContentTypeCreateModel(key: key); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -150,10 +150,10 @@ public partial class ContentTypeEditingServiceTests { var propertyTypeKey = new Guid("82DDEBD8-D2CA-423E-B88D-6890F26152B4"); - var propertyTypeContainer = CreateContainer(); - var propertyTypeCreateModel = CreatePropertyType(key: propertyTypeKey, containerKey: propertyTypeContainer.Key); + var propertyTypeContainer = ContentTypePropertyContainerModel(); + var propertyTypeCreateModel = ContentTypePropertyTypeModel(key: propertyTypeKey, containerKey: propertyTypeContainer.Key); - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( propertyTypes: new[] { propertyTypeCreateModel }, containers: new[] { propertyTypeContainer }); @@ -174,12 +174,12 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Assign_Allowed_Types() { - var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result; - var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result; + var allowedOne = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result; + var allowedTwo = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result; Assert.IsNotNull(allowedOne); Assert.IsNotNull(allowedTwo); - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias), @@ -202,7 +202,7 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Assign_History_Cleanup() { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Cleanup = new ContentTypeCleanup { PreventCleanup = true, KeepAllVersionsNewerThanDays = 123, KeepLatestVersionPerDayForDays = 456 @@ -226,16 +226,16 @@ public partial class ContentTypeEditingServiceTests // Wondering where the last case is? Look at the test below. public async Task Can_Create_Composite(bool compositionIsElement, bool contentTypeIsElement) { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase", isElement: compositionIsElement); // Let's add a property to ensure that it passes through - var container = CreateContainer(); + var container = ContentTypePropertyContainerModel(); compositionBase.Containers = new[] { container }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: container.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: container.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -243,7 +243,7 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( isElement: contentTypeIsElement, compositions: new[] { @@ -273,17 +273,17 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Create_Property_Container_Structure_Matching_Composition_Container_Structure() { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase"); // Let's add a property to ensure that it passes through - var compositionTab = CreateContainer("Composition Tab", type: TabContainerType); - var compositionGroup = CreateContainer("Composition Group", type: GroupContainerType); + var compositionTab = ContentTypePropertyContainerModel("Composition Tab", type: TabContainerType); + var compositionGroup = ContentTypePropertyContainerModel("Composition Group", type: GroupContainerType); compositionGroup.ParentKey = compositionTab.Key; compositionBase.Containers = new[] { compositionTab, compositionGroup }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: compositionGroup.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: compositionGroup.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -291,19 +291,19 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, } ); - var tab = CreateContainer("Composition Tab", type: TabContainerType); - var group = CreateContainer("Composition Group", type: GroupContainerType); + var tab = ContentTypePropertyContainerModel("Composition Tab", type: TabContainerType); + var group = ContentTypePropertyContainerModel("Composition Group", type: GroupContainerType); group.ParentKey = tab.Key; createModel.Containers = new[] { tab, group }; - var property = CreatePropertyType("My Property", "myProperty", containerKey: group.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: group.Key); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -328,18 +328,18 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Property_Container_Aliases_Are_CamelCased_Names() { - var createModel = CreateCreateModel("Test", "test"); - var tab = CreateContainer("My Tab", type: TabContainerType); - var group1 = CreateContainer("My Group", type: GroupContainerType); + var createModel = ContentTypeCreateModel("Test", "test"); + var tab = ContentTypePropertyContainerModel("My Tab", type: TabContainerType); + var group1 = ContentTypePropertyContainerModel("My Group", type: GroupContainerType); group1.ParentKey = tab.Key; - var group2 = CreateContainer("AnotherGroup", type: GroupContainerType); + var group2 = ContentTypePropertyContainerModel("AnotherGroup", type: GroupContainerType); createModel.Containers = new[] { tab, group1, group2 }; - var property = CreatePropertyType("My Property", "myProperty", containerKey: group1.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: group1.Key); // assign some properties to the groups to make sure they're not cleaned out as "empty groups" createModel.Properties = new[] { - CreatePropertyType("My Property 1", "myProperty1", containerKey: group1.Key), - CreatePropertyType("My Property 2", "myProperty2", containerKey: group2.Key) + ContentTypePropertyTypeModel("My Property 1", "myProperty1", containerKey: group1.Key), + ContentTypePropertyTypeModel("My Property 2", "myProperty2", containerKey: group2.Key) }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -360,7 +360,7 @@ public partial class ContentTypeEditingServiceTests // Even if it's an element type, however if we look at the comment in GetAvailableCompositeContentTypes // We see that element types are not suppose to be allowed to be composed by non-element types. // Since this breaks models builder evidently. - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", isElement: false); @@ -368,7 +368,7 @@ public partial class ContentTypeEditingServiceTests Assert.IsTrue(compositionResult.Success); var compositionType = compositionResult.Result; - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( "Content Type Using Composition", compositions: new[] { @@ -393,12 +393,12 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task ContentType_Containing_Composition_Cannot_Be_Used_As_Composition() { - var compositionBase = CreateCreateModel("CompositionBase"); + var compositionBase = ContentTypeCreateModel("CompositionBase"); var baseResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); Assert.IsTrue(baseResult.Success); - var composition = CreateCreateModel( + var composition = ContentTypeCreateModel( "Composition", compositions: new[] { @@ -412,7 +412,7 @@ public partial class ContentTypeEditingServiceTests Assert.IsTrue(compositionResult.Success); // This is not allowed because the composition also has a composition (compositionBase). - var invalidComposition = CreateCreateModel( + var invalidComposition = ContentTypeCreateModel( "Invalid", compositions: new[] { @@ -437,15 +437,15 @@ public partial class ContentTypeEditingServiceTests public async Task Can_Create_Child() { - var parentProperty = CreatePropertyType("Parent Property", "parentProperty"); - var parentModel = CreateCreateModel( + var parentProperty = ContentTypePropertyTypeModel("Parent Property", "parentProperty"); + var parentModel = ContentTypeCreateModel( "Parent", propertyTypes: new[] { parentProperty }); var parentResult = await ContentTypeEditingService.CreateAsync(parentModel, Constants.Security.SuperUserKey); Assert.IsTrue(parentResult.Success); - var childProperty = CreatePropertyType("Child Property", "childProperty"); + var childProperty = ContentTypePropertyTypeModel("Child Property", "childProperty"); var parentKey = parentResult.Result!.Key; Composition[] composition = { @@ -455,7 +455,7 @@ public partial class ContentTypeEditingServiceTests }, }; - var childModel = CreateCreateModel( + var childModel = ContentTypeCreateModel( "Child", propertyTypes: new[] { childProperty }, compositions: composition); @@ -480,15 +480,15 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Create_Grandchild() { - var rootProperty = CreatePropertyType("Root property"); - ContentTypeCreateModel rootModel = CreateCreateModel( + var rootProperty = ContentTypePropertyTypeModel("Root property"); + ContentTypeCreateModel rootModel = ContentTypeCreateModel( "Root", propertyTypes: new[] { rootProperty }); var rootResult = await ContentTypeEditingService.CreateAsync(rootModel, Constants.Security.SuperUserKey); Assert.IsTrue(rootResult.Success); - var childProperty = CreatePropertyType("Child Property", "childProperty"); + var childProperty = ContentTypePropertyTypeModel("Child Property", "childProperty"); var rootKey = rootResult.Result!.Key; Composition[] composition = { @@ -498,7 +498,7 @@ public partial class ContentTypeEditingServiceTests }, }; - var childModel = CreateCreateModel( + var childModel = ContentTypeCreateModel( "Child", propertyTypes: new[] { childProperty }, compositions: composition); @@ -506,7 +506,7 @@ public partial class ContentTypeEditingServiceTests var childResult = await ContentTypeEditingService.CreateAsync(childModel, Constants.Security.SuperUserKey); Assert.IsTrue(childResult.Success); - var grandchildProperty = CreatePropertyType("Grandchild Property", "grandchildProperty"); + var grandchildProperty = ContentTypePropertyTypeModel("Grandchild Property", "grandchildProperty"); var childKey = childResult.Result!.Key; Composition[] grandchildComposition = { @@ -516,7 +516,7 @@ public partial class ContentTypeEditingServiceTests }, }; - var grandchildModel = CreateCreateModel( + var grandchildModel = ContentTypeCreateModel( "Grandchild", propertyTypes: new[] { grandchildProperty }, compositions: grandchildComposition); @@ -549,12 +549,12 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Be_Both_Parent_And_Composition() { - var compositionBase = CreateCreateModel("CompositionBase"); + var compositionBase = ContentTypeCreateModel("CompositionBase"); var baseResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); Assert.IsTrue(baseResult.Success); - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition @@ -578,15 +578,15 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Have_Multiple_Inheritance() { - var parentModel1 = CreateCreateModel("Parent1"); - var parentModel2 = CreateCreateModel("Parent2"); + var parentModel1 = ContentTypeCreateModel("Parent1"); + var parentModel2 = ContentTypeCreateModel("Parent2"); var parentKey1 = (await ContentTypeEditingService.CreateAsync(parentModel1, Constants.Security.SuperUserKey)).Result?.Key; Assert.IsTrue(parentKey1.HasValue); var parentKey2 = (await ContentTypeEditingService.CreateAsync(parentModel2, Constants.Security.SuperUserKey)).Result?.Key; Assert.IsTrue(parentKey2.HasValue); - var childProperty = CreatePropertyType("Child Property", "childProperty"); + var childProperty = ContentTypePropertyTypeModel("Child Property", "childProperty"); Composition[] composition = { new() @@ -599,7 +599,7 @@ public partial class ContentTypeEditingServiceTests }, }; - var childModel = CreateCreateModel( + var childModel = ContentTypeCreateModel( "Child", propertyTypes: new[] { childProperty }, compositions: composition); @@ -614,15 +614,15 @@ public partial class ContentTypeEditingServiceTests public async Task Cannot_Specify_Duplicate_PropertyType_Alias_From_Compositions() { var propertyTypeAlias = "testproperty"; - var compositionPropertyType = CreatePropertyType("Test Property", propertyTypeAlias); - var compositionBase = CreateCreateModel( + var compositionPropertyType = ContentTypePropertyTypeModel("Test Property", propertyTypeAlias); + var compositionBase = ContentTypeCreateModel( "CompositionBase", propertyTypes: new[] { compositionPropertyType }); var compositionBaseResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); Assert.IsTrue(compositionBaseResult.Success); - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition @@ -632,7 +632,7 @@ public partial class ContentTypeEditingServiceTests }, propertyTypes: new[] { - CreatePropertyType("Test Property", propertyTypeAlias) + ContentTypePropertyTypeModel("Test Property", propertyTypeAlias) }); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.Multiple(() => @@ -645,7 +645,7 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Specify_Non_Existent_DocType_As_Composition() { - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition @@ -665,7 +665,7 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Mix_Inheritance_And_ParentKey() { - var parentModel = CreateCreateModel("Parent"); + var parentModel = ContentTypeCreateModel("Parent"); var parentKey = (await ContentTypeEditingService.CreateAsync(parentModel, Constants.Security.SuperUserKey)).Result?.Key; Assert.IsTrue(parentKey.HasValue); @@ -682,9 +682,9 @@ public partial class ContentTypeEditingServiceTests } }; - var childModel = CreateCreateModel( + var childModel = ContentTypeCreateModel( "Child", - parentKey: container.Key, + containerKey: container.Key, compositions: composition); var result = await ContentTypeEditingService.CreateAsync(childModel, Constants.Security.SuperUserKey); @@ -696,13 +696,13 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Use_As_ParentKey() { - var parentModel = CreateCreateModel("Parent"); + var parentModel = ContentTypeCreateModel("Parent"); var parentKey = (await ContentTypeEditingService.CreateAsync(parentModel, Constants.Security.SuperUserKey)).Result?.Key; Assert.IsTrue(parentKey.HasValue); - var childModel = CreateCreateModel( + var childModel = ContentTypeCreateModel( "Child", - parentKey: parentKey.Value); + containerKey: parentKey.Value); var result = await ContentTypeEditingService.CreateAsync(childModel, Constants.Security.SuperUserKey); @@ -737,8 +737,8 @@ public partial class ContentTypeEditingServiceTests foreach (var alias in propertyTypeAliases) { - var propertyType = CreatePropertyType("Test Property", alias); - var createModel = CreateCreateModel("Test", propertyTypes: new[] { propertyType }); + var propertyType = ContentTypePropertyTypeModel("Test Property", alias); + var createModel = ContentTypeCreateModel("Test", propertyTypes: new[] { propertyType }); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); @@ -752,9 +752,9 @@ public partial class ContentTypeEditingServiceTests [TestCase("testProperty", "testproperty")] public async Task Cannot_Use_Duplicate_PropertyType_Alias(string propertyTypeAlias1, string propertyTypeAlias2) { - var propertyType1 = CreatePropertyType("Test Property", propertyTypeAlias1); - var propertyType2 = CreatePropertyType("Test Property", propertyTypeAlias2); - var createModel = CreateCreateModel("Test", propertyTypes: new[] { propertyType1, propertyType2 }); + var propertyType1 = ContentTypePropertyTypeModel("Test Property", propertyTypeAlias1); + var propertyType2 = ContentTypePropertyTypeModel("Test Property", propertyTypeAlias2); + var createModel = ContentTypeCreateModel("Test", propertyTypes: new[] { propertyType1, propertyType2 }); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); @@ -769,8 +769,8 @@ public partial class ContentTypeEditingServiceTests [TestCase("TESTALIAS", "testAlias")] public async Task Cannot_Use_Alias_As_PropertyType_Alias(string contentTypeAlias, string propertyTypeAlias) { - var propertyType = CreatePropertyType("Test Property", propertyTypeAlias); - var createModel = CreateCreateModel("Test", contentTypeAlias, propertyTypes: new[] { propertyType }); + var propertyType = ContentTypePropertyTypeModel("Test Property", propertyTypeAlias); + var createModel = ContentTypeCreateModel("Test", contentTypeAlias, propertyTypes: new[] { propertyType }); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); @@ -780,8 +780,8 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Use_Non_Existing_DataType_For_PropertyType() { - var propertyType = CreatePropertyType("Test Property", "testProperty", dataTypeKey: Guid.NewGuid()); - var createModel = CreateCreateModel("Test", "test", propertyTypes: new[] { propertyType }); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty", dataTypeKey: Guid.NewGuid()); + var createModel = ContentTypeCreateModel("Test", "test", propertyTypes: new[] { propertyType }); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); @@ -791,8 +791,8 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Use_Empty_Alias_For_PropertyType() { - var propertyType = CreatePropertyType("Test Property", string.Empty); - var createModel = CreateCreateModel("Test", "test", propertyTypes: new[] { propertyType }); + var propertyType = ContentTypePropertyTypeModel("Test Property", string.Empty); + var createModel = ContentTypeCreateModel("Test", "test", propertyTypes: new[] { propertyType }); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); @@ -802,9 +802,9 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Use_Empty_Name_For_PropertyType_Container() { - var container = CreateContainer(string.Empty); - var propertyType = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key); - var createModel = CreateCreateModel("Test", "test", propertyTypes: new[] { propertyType }); + var container = ContentTypePropertyContainerModel(string.Empty); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty", containerKey: container.Key); + var createModel = ContentTypeCreateModel("Test", "test", propertyTypes: new[] { propertyType }); createModel.Containers = new[] { container }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -823,7 +823,7 @@ public partial class ContentTypeEditingServiceTests [TestCase("SYSTEM")] public async Task Cannot_Use_Invalid_Alias(string contentTypeAlias) { - var createModel = CreateCreateModel("Test", contentTypeAlias); + var createModel = ContentTypeCreateModel("Test", contentTypeAlias); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); @@ -833,11 +833,11 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Use_Existing_Alias() { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsTrue(result.Success); - createModel = CreateCreateModel("Test 2", "test"); + createModel = ContentTypeCreateModel("Test 2", "test"); result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); Assert.AreEqual(ContentTypeOperationStatus.DuplicateAlias, result.Status); @@ -846,15 +846,15 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Add_Container_From_Composition() { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase"); // Let's add a property to ensure that it passes through - var compositionContainer = CreateContainer("Composition Tab"); + var compositionContainer = ContentTypePropertyContainerModel("Composition Tab"); compositionBase.Containers = new[] { compositionContainer }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -862,7 +862,7 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, @@ -871,7 +871,7 @@ public partial class ContentTypeEditingServiceTests // this is invalid; the model should not contain the composition container definitions (they will be resolved by ContentTypeEditingService) createModel.Containers = new[] { compositionContainer }; - var property = CreatePropertyType("My Property", "myProperty", containerKey: compositionContainer.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: compositionContainer.Key); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -882,14 +882,14 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Duplicate_Container_Key_From_Composition() { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase"); - var compositionContainer = CreateContainer("Composition Tab"); + var compositionContainer = ContentTypePropertyContainerModel("Composition Tab"); compositionBase.Containers = new[] { compositionContainer }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -897,7 +897,7 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, @@ -905,9 +905,9 @@ public partial class ContentTypeEditingServiceTests ); // this is invalid; cannot reuse the container key - var container = CreateContainer("My Group", type: GroupContainerType, key: compositionContainer.Key); + var container = ContentTypePropertyContainerModel("My Group", type: GroupContainerType, key: compositionContainer.Key); createModel.Containers = new[] { container }; - var property = CreatePropertyType("My Property", "myProperty", containerKey: container.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: container.Key); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -919,12 +919,12 @@ public partial class ContentTypeEditingServiceTests public async Task Cannot_Have_Duplicate_Container_Key() { // Create doc type using the composition - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); // this is invalid; cannot reuse the container key var containerKey = Guid.NewGuid(); - var container1 = CreateContainer("My Group 1", key: containerKey); - var container2 = CreateContainer("My Group 2", key: containerKey); + var container1 = ContentTypePropertyContainerModel("My Group 1", key: containerKey); + var container2 = ContentTypePropertyContainerModel("My Group 2", key: containerKey); createModel.Containers = new[] { container1, container2 }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -935,14 +935,14 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Add_Property_To_Missing_Container() { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase"); - var compositionContainer = CreateContainer("Composition Tab"); + var compositionContainer = ContentTypePropertyContainerModel("Composition Tab"); compositionBase.Containers = new[] { compositionContainer }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -950,7 +950,7 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, @@ -958,7 +958,7 @@ public partial class ContentTypeEditingServiceTests ); // this is invalid; cannot add properties to non-existing containers - var property = CreatePropertyType("My Property", "myProperty", containerKey: Guid.NewGuid()); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: Guid.NewGuid()); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -970,14 +970,14 @@ public partial class ContentTypeEditingServiceTests public async Task Cannot_Add_Property_Container_To_Missing_Container() { // Create doc type using the composition - var createModel = CreateCreateModel(); + var createModel = ContentTypeCreateModel(); - var group = CreateContainer("My Group", type: GroupContainerType); + var group = ContentTypePropertyContainerModel("My Group", type: GroupContainerType); // this is invalid; a container cannot have a non-existing parent container key group.ParentKey = Guid.NewGuid(); createModel.Containers = new[] { group }; - var property = CreatePropertyType("My Property", "myProperty", containerKey: group.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: group.Key); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -988,15 +988,15 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Create_Property_In_Composition_Container() { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase"); // Let's add a property to ensure that it passes through - var compositionContainer = CreateContainer("Composition Tab"); + var compositionContainer = ContentTypePropertyContainerModel("Composition Tab"); compositionBase.Containers = new[] { compositionContainer }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -1004,7 +1004,7 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, @@ -1012,7 +1012,7 @@ public partial class ContentTypeEditingServiceTests ); // this is invalid; cannot add a property on a container that belongs to the composition (the container must be duplicated to the content type itself) - var property = CreatePropertyType("My Property", "myProperty", containerKey: compositionContainer.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: compositionContainer.Key); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -1023,15 +1023,15 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Create_Property_Container_In_Composition_Container() { - var compositionBase = CreateCreateModel( + var compositionBase = ContentTypeCreateModel( "Composition Base", "compositionBase"); // Let's add a property to ensure that it passes through - var compositionContainer = CreateContainer("Composition Tab"); + var compositionContainer = ContentTypePropertyContainerModel("Composition Tab"); compositionBase.Containers = new[] { compositionContainer }; - var compositionProperty = CreatePropertyType("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: compositionContainer.Key); compositionBase.Properties = new[] { compositionProperty }; var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); @@ -1039,7 +1039,7 @@ public partial class ContentTypeEditingServiceTests var compositionType = compositionResult.Result; // Create doc type using the composition - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( compositions: new[] { new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, @@ -1047,14 +1047,43 @@ public partial class ContentTypeEditingServiceTests ); // this is invalid; cannot create a new container within a parent container that belongs to the composition (the parent container must be duplicated to the content type itself) - var container = CreateContainer("My Group", type: GroupContainerType); + var container = ContentTypePropertyContainerModel("My Group", type: GroupContainerType); container.ParentKey = compositionContainer.Key; createModel.Containers = new[] { container }; - var property = CreatePropertyType("My Property", "myProperty", containerKey: container.Key); + var property = ContentTypePropertyTypeModel("My Property", "myProperty", containerKey: container.Key); createModel.Properties = new[] { property }; var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); Assert.AreEqual(ContentTypeOperationStatus.MissingContainer, result.Status); } + + [Test] + public async Task Cannot_Create_Composite_With_MediaType() + { + var compositionBase = MediaTypeCreateModel("Composition Base"); + + // Let's add a property to ensure that it passes through + var container = MediaTypePropertyContainerModel(); + compositionBase.Containers = new[] { container }; + + var compositionProperty = MediaTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: container.Key); + compositionBase.Properties = new[] { compositionProperty }; + + var compositionResult = await MediaTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); + Assert.IsTrue(compositionResult.Success); + var compositionType = compositionResult.Result; + + // Create doc type using the composition + var createModel = ContentTypeCreateModel( + compositions: new[] + { + new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, + } + ); + + var result = await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + Assert.IsFalse(result.Success); + Assert.AreEqual(ContentTypeOperationStatus.InvalidComposition, result.Status); + } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.GetAvailableCompositions.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.GetAvailableCompositions.cs new file mode 100644 index 0000000000..356d78d931 --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.GetAvailableCompositions.cs @@ -0,0 +1,242 @@ +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.ContentTypeEditing; + +namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; + +public partial class ContentTypeEditingServiceTests +{ + [TestCase(true)] + [TestCase(false)] + public async Task Can_Get_Available_Compositions_Only_From_Content_Type_Key(bool isElement) + { + var contentType1 = CreateBasicContentTypeModelWithSingleProperty("Content type 1", "Property 1", isElement); + var result1 = await ContentTypeEditingService.CreateAsync(contentType1, Constants.Security.SuperUserKey); + + var contentType2 = CreateBasicContentTypeModelWithSingleProperty("Content type 2", "Property 2", isElement); + var result2 = await ContentTypeEditingService.CreateAsync(contentType2, Constants.Security.SuperUserKey); + + var contentType3 = CreateBasicContentTypeModelWithSingleProperty("Content type 3", "Property 3", isElement); + var result3 = await ContentTypeEditingService.CreateAsync(contentType3, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + result1.Result!.Key, + Enumerable.Empty(), + Enumerable.Empty(), + isElement); + + Assert.AreEqual(2, availableCompositions.Count()); + + // Verify that contentType2 and contentType3 are present in available compositions + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed)); + } + + [TestCase(true)] + [TestCase(false)] + public async Task Available_Compositions_For_Content_Type_Are_Not_Media_Types(bool isElement) + { + var contentType = CreateBasicContentTypeModelWithSingleProperty("Content type", "Property 1", isElement); + var result1 = await ContentTypeEditingService.CreateAsync(contentType, Constants.Security.SuperUserKey); + + var container2 = MediaTypePropertyContainerModel(); + var propertyType2 = MediaTypePropertyTypeModel("Property 2", containerKey: container2.Key); + var mediaType = MediaTypeCreateModel( + "Media type", + propertyTypes: new[] { propertyType2 }, + containers: new[] { container2 }); + + await MediaTypeEditingService.CreateAsync(mediaType, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + result1.Result!.Key, + Enumerable.Empty(), + Enumerable.Empty(), + false); + + Assert.AreEqual(0, availableCompositions.Count()); + } + + [TestCase(true)] + [TestCase(false)] + public async Task Can_Get_Available_Compositions_For_New_Item(bool isElement) + { + var contentType1 = CreateBasicContentTypeModelWithSingleProperty("Content type 1", "Property 1", isElement); + var result1 = await ContentTypeEditingService.CreateAsync(contentType1, Constants.Security.SuperUserKey); + + var contentType2 = CreateBasicContentTypeModelWithSingleProperty("Content type 2", "Property 2", isElement); + var result2 = await ContentTypeEditingService.CreateAsync(contentType2, Constants.Security.SuperUserKey); + + var contentType3 = CreateBasicContentTypeModelWithSingleProperty("Content type 3", "Property 3", isElement); + var result3 = await ContentTypeEditingService.CreateAsync(contentType3, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + null, + Enumerable.Empty(), + Enumerable.Empty(), + isElement); + + Assert.AreEqual(3, availableCompositions.Count()); + + // Verify that all content types are present in available compositions + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result1.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed)); + } + + [Test] + public async Task Available_Compositions_For_Element_Types_Are_Only_Element_Types() + { + var elementType1 = CreateBasicContentTypeModelWithSingleProperty("Element type 1", "Property 1", true); + var result1 = await ContentTypeEditingService.CreateAsync(elementType1, Constants.Security.SuperUserKey); + + var elementType2 = CreateBasicContentTypeModelWithSingleProperty("Element type 2", "Property 2", true); + var result2 = await ContentTypeEditingService.CreateAsync(elementType2, Constants.Security.SuperUserKey); + + var elementType3 = CreateBasicContentTypeModelWithSingleProperty("Element type 3", "Property 3", true); + var result3 = await ContentTypeEditingService.CreateAsync(elementType3, Constants.Security.SuperUserKey); + + var contentType = CreateBasicContentTypeModelWithSingleProperty("Content type", "Property 4", false); + await ContentTypeEditingService.CreateAsync(contentType, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + result1.Result!.Key, + Enumerable.Empty(), + Enumerable.Empty(), + true); + + Assert.AreEqual(2, availableCompositions.Count()); + + // Verify that only element types are present in available compositions + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed)); + } + + [Test] + public async Task Available_Compositions_For_Content_Types_Can_Be_Element_Types() + { + var elementType1 = CreateBasicContentTypeModelWithSingleProperty("Element type 1", "Property 1", true); + var result1 = await ContentTypeEditingService.CreateAsync(elementType1, Constants.Security.SuperUserKey); + + var elementType2 = CreateBasicContentTypeModelWithSingleProperty("Element type 2", "Property 2", true); + var result2 = await ContentTypeEditingService.CreateAsync(elementType2, Constants.Security.SuperUserKey); + + var elementType3 = CreateBasicContentTypeModelWithSingleProperty("Element type 3", "Property 3", true); + var result3 = await ContentTypeEditingService.CreateAsync(elementType3, Constants.Security.SuperUserKey); + + var contentType1 = CreateBasicContentTypeModelWithSingleProperty("Content type 1", "Property 4", false); + var result4 = await ContentTypeEditingService.CreateAsync(contentType1, Constants.Security.SuperUserKey); + + var contentType2 = CreateBasicContentTypeModelWithSingleProperty("Content type 2", "Property 5", false); + var result5 = await ContentTypeEditingService.CreateAsync(contentType2, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + result4.Result!.Key, + Enumerable.Empty(), + Enumerable.Empty(), + false); + + Assert.AreEqual(4, availableCompositions.Count()); + + // Verify that the rest of content types (element types included) are present in available compositions + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result1.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result5.Result!.Key && compositionsResult.Allowed)); + } + + [TestCase(true)] + [TestCase(false)] + public async Task Content_Type_Picked_As_Composition_Is_Available_But_Not_Allowed(bool isElement) + { + var contentType1 = CreateBasicContentTypeModelWithSingleProperty("Content type 1", "Property 1", isElement); + var result1 = await ContentTypeEditingService.CreateAsync(contentType1, Constants.Security.SuperUserKey); + + var contentType2 = CreateBasicContentTypeModelWithSingleProperty("Content type 2", "Property 2", isElement); + var result2 = await ContentTypeEditingService.CreateAsync(contentType2, Constants.Security.SuperUserKey); + + var contentType3 = CreateBasicContentTypeModelWithSingleProperty("Content type 3", "Property 3", isElement); + var result3 = await ContentTypeEditingService.CreateAsync(contentType3, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + null, + new[] { result2.Result!.Key }, + Enumerable.Empty(), + isElement); + + // Verify that all content types are present in available compositions + Assert.AreEqual(3, availableCompositions.Count()); + + // Verify that contentType2 is not allowed because it is selected as composition already, so cannot be picked again + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result1.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed == false)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed)); + } + + [TestCase(true)] + [TestCase(false)] + public async Task Content_Type_With_Matching_Composition_Property_Is_Available_But_Not_Allowed(bool isElement) + { + var contentType1 = CreateBasicContentTypeModelWithSingleProperty("Content type 1", "Property 1", isElement); + var result1 = await ContentTypeEditingService.CreateAsync(contentType1, Constants.Security.SuperUserKey); + + var contentType2 = CreateBasicContentTypeModelWithSingleProperty("Content type 2", "Property 2", isElement); + var result2 = await ContentTypeEditingService.CreateAsync(contentType2, Constants.Security.SuperUserKey); + + var contentType3 = CreateBasicContentTypeModelWithSingleProperty("Content type 3", "Property 3", isElement); + var result3 = await ContentTypeEditingService.CreateAsync(contentType3, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await ContentTypeEditingService.GetAvailableCompositionsAsync( + null, + Enumerable.Empty(), + new[] { "property3" }, + isElement); + + // Verify that all content types are present in available compositions + Assert.AreEqual(3, availableCompositions.Count()); + + // Verify that contentType3 is not allowed because it has a matching property with the current state of the item we are using to look + // for available compositions + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result1.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed == false)); + } + + private ContentTypeCreateModel CreateBasicContentTypeModelWithSingleProperty(string contentTypeName, string propertyName, bool isElement) + { + var container = ContentTypePropertyContainerModel(); + var propertyType = ContentTypePropertyTypeModel(propertyName, containerKey: container.Key); + var contentType = ContentTypeCreateModel( + contentTypeName, + isElement: isElement, + propertyTypes: new[] { propertyType }, + containers: new[] { container }); + + return contentType; + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Update.cs index 51dbe3c3ab..f705f2732f 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.Update.cs @@ -12,13 +12,13 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Update_All_Basic_Settings(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); createModel.Description = "This is the Test description"; createModel.Icon = "icon icon-something"; createModel.AllowedAsRoot = true; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test updated", "testUpdated", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test updated", "testUpdated", isElement: isElement); updateModel.Description = "This is the Test description updated"; updateModel.Icon = "icon icon-something-updated"; updateModel.AllowedAsRoot = false; @@ -46,13 +46,13 @@ public partial class ContentTypeEditingServiceTests [TestCase(true, true)] public async Task Can_Update_Variation(bool variesByCulture, bool variesBySegment) { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.VariesByCulture = variesByCulture; createModel.VariesBySegment = variesBySegment; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.VariesByCulture = !variesByCulture; updateModel.VariesBySegment = !variesBySegment; @@ -70,17 +70,17 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Add_Allowed_Types() { - var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; - var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; + var allowedOne = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; + var allowedTwo = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias), }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias), @@ -104,10 +104,10 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Remove_Allowed_Types() { - var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; - var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; + var allowedOne = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; + var allowedTwo = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias), @@ -115,7 +115,7 @@ public partial class ContentTypeEditingServiceTests }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.AllowedContentTypes = Array.Empty(); var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey); @@ -133,10 +133,10 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Rearrange_Allowed_Types() { - var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; - var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; + var allowedOne = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; + var allowedTwo = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 0, allowedOne.Alias), @@ -144,7 +144,7 @@ public partial class ContentTypeEditingServiceTests }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 1, allowedOne.Alias), @@ -168,11 +168,11 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Add_Self_To_Allowed_Types() { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; var id = contentType.Id; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.AllowedContentTypes = new[] { new ContentTypeSort(contentType.Key, 0, contentType.Alias) @@ -195,18 +195,18 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Add_Properties(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container = CreateContainer(); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container = ContentTypePropertyContainerModel(); createModel.Containers = new[] { container }; - var propertyType = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty", containerKey: container.Key); createModel.Properties = new[] { propertyType }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); updateModel.Containers = new[] { container }; - var newPropertyType = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container.Key); + var newPropertyType = ContentTypePropertyTypeModel("Test Property 2", "testProperty2", containerKey: container.Key); newPropertyType.SortOrder = 0; propertyType.SortOrder = 1; updateModel.Properties = new[] { propertyType, newPropertyType }; @@ -239,16 +239,16 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Remove_Properties(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container = CreateContainer(); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container = ContentTypePropertyContainerModel(); createModel.Containers = new[] { container }; - var propertyType = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty", containerKey: container.Key); createModel.Properties = new[] { propertyType }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); updateModel.Containers = new[] { container }; updateModel.Properties = Array.Empty(); @@ -271,16 +271,16 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Edit_Properties(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var propertyType = CreatePropertyType("Test Property", "testProperty"); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var propertyType = ContentTypePropertyTypeModel("Test Property", "testProperty"); propertyType.Description = "The description"; createModel.Properties = new[] { propertyType }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; var originalPropertyTypeKey = contentType.PropertyTypes.First().Key; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); - propertyType = CreatePropertyType("Test Property 2", "testProperty", key: originalPropertyTypeKey); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); + propertyType = ContentTypePropertyTypeModel("Test Property 2", "testProperty", key: originalPropertyTypeKey); propertyType.Description = "The updated description"; updateModel.Properties = new[] { propertyType }; @@ -309,18 +309,18 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Move_Properties_To_Another_Container(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container1 = CreateContainer("One"); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container1 = ContentTypePropertyContainerModel("One"); createModel.Containers = new[] { container1 }; - var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1", containerKey: container1.Key); - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container1.Key); + var propertyType1 = ContentTypePropertyTypeModel("Test Property 1", "testProperty1", containerKey: container1.Key); + var propertyType2 = ContentTypePropertyTypeModel("Test Property 2", "testProperty2", containerKey: container1.Key); createModel.Properties = new[] { propertyType1, propertyType2 }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); - var container2 = CreateContainer("Two"); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); + var container2 = ContentTypePropertyContainerModel("Two"); container2.SortOrder = 0; container1.SortOrder = 1; updateModel.Containers = new[] { container1, container2 }; @@ -351,20 +351,20 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Rearrange_Containers(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container1 = CreateContainer("One"); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container1 = ContentTypePropertyContainerModel("One"); container1.SortOrder = 0; - var container2 = CreateContainer("Two"); + var container2 = ContentTypePropertyContainerModel("Two"); container2.SortOrder = 1; createModel.Containers = new[] { container1, container2 }; - var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1", containerKey: container1.Key); - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container2.Key); + var propertyType1 = ContentTypePropertyTypeModel("Test Property 1", "testProperty1", containerKey: container1.Key); + var propertyType2 = ContentTypePropertyTypeModel("Test Property 2", "testProperty2", containerKey: container2.Key); createModel.Properties = new[] { propertyType1, propertyType2 }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); container2.SortOrder = 0; container1.SortOrder = 1; updateModel.Containers = new[] { container1, container2 }; @@ -390,18 +390,18 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Can_Make_Properties_Orphaned(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container1 = CreateContainer("One"); - var container2 = CreateContainer("Two"); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container1 = ContentTypePropertyContainerModel("One"); + var container2 = ContentTypePropertyContainerModel("Two"); createModel.Containers = new[] { container1, container2 }; - var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1", containerKey: container1.Key); - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container2.Key); + var propertyType1 = ContentTypePropertyTypeModel("Test Property 1", "testProperty1", containerKey: container1.Key); + var propertyType2 = ContentTypePropertyTypeModel("Test Property 2", "testProperty2", containerKey: container2.Key); createModel.Properties = new[] { propertyType1, propertyType2 }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); updateModel.Containers = new[] { container1 }; propertyType2.ContainerKey = null; updateModel.Properties = new[] { propertyType1, propertyType2 }; @@ -427,18 +427,18 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Add_Compositions() { - var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1"); - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2"); + var propertyType1 = ContentTypePropertyTypeModel("Test Property 1", "testProperty1"); + var propertyType2 = ContentTypePropertyTypeModel("Test Property 2", "testProperty2"); - var compositionCreateModel = CreateCreateModel("Composition", "composition"); + var compositionCreateModel = ContentTypeCreateModel("Composition", "composition"); compositionCreateModel.Properties = new[] { propertyType1 }; var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Properties = new[] { propertyType2 }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.Properties = new[] { propertyType2 }; updateModel.Compositions = new[] { @@ -464,14 +464,14 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Reapply_Compositions() { - var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1"); - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2"); + var propertyType1 = ContentTypePropertyTypeModel("Test Property 1", "testProperty1"); + var propertyType2 = ContentTypePropertyTypeModel("Test Property 2", "testProperty2"); - var compositionCreateModel = CreateCreateModel("Composition", "composition"); + var compositionCreateModel = ContentTypeCreateModel("Composition", "composition"); compositionCreateModel.Properties = new[] { propertyType1 }; var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Properties = new[] { propertyType2 }; createModel.Compositions = new[] { @@ -479,7 +479,7 @@ public partial class ContentTypeEditingServiceTests }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.Properties = new[] { propertyType2 }; updateModel.Compositions = new[] { @@ -505,14 +505,14 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Remove_Compositions() { - var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1"); - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2"); + var propertyType1 = ContentTypePropertyTypeModel("Test Property 1", "testProperty1"); + var propertyType2 = ContentTypePropertyTypeModel("Test Property 2", "testProperty2"); - var compositionCreateModel = CreateCreateModel("Composition", "composition"); + var compositionCreateModel = ContentTypeCreateModel("Composition", "composition"); compositionCreateModel.Properties = new[] { propertyType1 }; var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Properties = new[] { propertyType2 }; createModel.Compositions = new[] { @@ -520,7 +520,7 @@ public partial class ContentTypeEditingServiceTests }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.Properties = new[] { propertyType2 }; updateModel.Compositions = Array.Empty(); @@ -540,9 +540,9 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Reapply_Inheritance() { - var parentContentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!; + var parentContentType = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( "Child", compositions: new Composition[] { @@ -552,7 +552,7 @@ public partial class ContentTypeEditingServiceTests var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; var originalPath = contentType.Path; - var updateModel = CreateUpdateModel( + var updateModel = ContentTypeUpdateModel( "Child", compositions: new Composition[] { @@ -575,14 +575,14 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Can_Update_History_Cleanup() { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Cleanup = new ContentTypeCleanup { PreventCleanup = true, KeepAllVersionsNewerThanDays = 123, KeepLatestVersionPerDayForDays = 456 }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test updated", "testUpdated"); + var updateModel = ContentTypeUpdateModel("Test updated", "testUpdated"); updateModel.Cleanup = new ContentTypeCleanup { PreventCleanup = false, KeepAllVersionsNewerThanDays = 234, KeepLatestVersionPerDayForDays = 567 @@ -605,16 +605,16 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Cannot_Move_Properties_To_Non_Existing_Containers(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container = CreateContainer("One"); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container = ContentTypePropertyContainerModel("One"); createModel.Containers = new[] { container }; - var property = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key); + var property = ContentTypePropertyTypeModel("Test Property", "testProperty", containerKey: container.Key); createModel.Properties = new[] { property }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); property.ContainerKey = Guid.NewGuid(); updateModel.Containers = new[] { container }; updateModel.Properties = new[] { property }; @@ -628,16 +628,16 @@ public partial class ContentTypeEditingServiceTests [TestCase(true)] public async Task Cannot_Move_Containers_To_Non_Existing_Containers(bool isElement) { - var createModel = CreateCreateModel("Test", "test", isElement: isElement); - var container = CreateContainer("One"); + var createModel = ContentTypeCreateModel("Test", "test", isElement: isElement); + var container = ContentTypePropertyContainerModel("One"); createModel.Containers = new[] { container }; - var property = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key); + var property = ContentTypePropertyTypeModel("Test Property", "testProperty", containerKey: container.Key); createModel.Properties = new[] { property }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test", isElement: isElement); + var updateModel = ContentTypeUpdateModel("Test", "test", isElement: isElement); container.ParentKey = Guid.NewGuid(); updateModel.Containers = new[] { container }; updateModel.Properties = new[] { property }; @@ -650,12 +650,12 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Add_Self_As_Composition() { - var property = CreatePropertyType("Test Property", "testProperty"); - var createModel = CreateCreateModel("Test", "test"); + var property = ContentTypePropertyTypeModel("Test Property", "testProperty"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Properties = new[] { property }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.Properties = new[] { property }; updateModel.Compositions = new[] { @@ -670,10 +670,10 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Change_Inheritance() { - var parentContentType1 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent1"), Constants.Security.SuperUserKey)).Result!; - var parentContentType2 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent2"), Constants.Security.SuperUserKey)).Result!; + var parentContentType1 = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent1"), Constants.Security.SuperUserKey)).Result!; + var parentContentType2 = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent2"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( "Child", compositions: new Composition[] { @@ -682,7 +682,7 @@ public partial class ContentTypeEditingServiceTests var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel( + var updateModel = ContentTypeUpdateModel( "Child", compositions: new Composition[] { @@ -697,10 +697,10 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Add_Inheritance() { - var parentContentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!; - var contentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Child"), Constants.Security.SuperUserKey)).Result!; + var parentContentType = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!; + var contentType = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Child"), Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel( + var updateModel = ContentTypeUpdateModel( "Child", compositions: new Composition[] { @@ -715,10 +715,10 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Add_Multiple_Inheritance() { - var parentContentType1 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent1"), Constants.Security.SuperUserKey)).Result!; - var parentContentType2 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent2"), Constants.Security.SuperUserKey)).Result!; + var parentContentType1 = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent1"), Constants.Security.SuperUserKey)).Result!; + var parentContentType2 = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent2"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel( + var createModel = ContentTypeCreateModel( "Child", compositions: new Composition[] { @@ -727,7 +727,7 @@ public partial class ContentTypeEditingServiceTests var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel( + var updateModel = ContentTypeUpdateModel( "Child", compositions: new Composition[] { @@ -743,11 +743,11 @@ public partial class ContentTypeEditingServiceTests [Test] public async Task Cannot_Add_Self_As_Inheritance() { - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.Compositions = new Composition[] { new() { CompositionType = CompositionType.Inheritance, Key = contentType.Key } @@ -763,10 +763,10 @@ public partial class ContentTypeEditingServiceTests { EntityContainer container = ContentTypeService.CreateContainer(Constants.System.Root, Guid.NewGuid(), "Test folder").Result!.Entity; - var parentContentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!; - var contentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Child", parentKey: container.Key), Constants.Security.SuperUserKey)).Result!; + var parentContentType = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!; + var contentType = (await ContentTypeEditingService.CreateAsync(ContentTypeCreateModel("Child", containerKey: container.Key), Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel( + var updateModel = ContentTypeUpdateModel( "Child", compositions: new Composition[] { @@ -782,17 +782,17 @@ public partial class ContentTypeEditingServiceTests [TestCase(CompositionType.Inheritance, CompositionType.Composition)] public async Task Cannot_Change_Composition_To_Inheritance(CompositionType from, CompositionType to) { - var compositionCreateModel = CreateCreateModel("Composition", "composition"); + var compositionCreateModel = ContentTypeCreateModel("Composition", "composition"); var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = ContentTypeCreateModel("Test", "test"); createModel.Compositions = new[] { new Composition { Key = compositionContentType.Key, CompositionType = from } }; var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = ContentTypeUpdateModel("Test", "test"); updateModel.Compositions = new[] { new Composition { Key = compositionContentType.Key, CompositionType = to } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.cs index 12b16e9832..8c99309a12 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.cs @@ -1,92 +1,5 @@ -using NUnit.Framework; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Models.ContentTypeEditing; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Services.ContentTypeEditing; -using Umbraco.Cms.Tests.Common.Testing; -using Umbraco.Cms.Tests.Integration.Testing; -using PropertyTypeValidation = Umbraco.Cms.Core.Models.ContentTypeEditing.PropertyTypeValidation; +namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; -namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; - -[TestFixture] -[UmbracoTest( - Database = UmbracoTestOptions.Database.NewSchemaPerTest, - PublishedRepositoryEvents = true, - WithApplication = true)] -public partial class ContentTypeEditingServiceTests : UmbracoIntegrationTest +public partial class ContentTypeEditingServiceTests : ContentTypeEditingServiceTestsBase { - private IContentTypeEditingService ContentTypeEditingService => GetRequiredService(); - - private IContentTypeService ContentTypeService => GetRequiredService(); - - private const string TabContainerType = "Tab"; - - private const string GroupContainerType = "Group"; - - private ContentTypeCreateModel CreateCreateModel( - string name = "Test", - string? alias = null, - Guid? key = null, - bool isElement = false, - Guid? parentKey = null, - IEnumerable? propertyTypes = null, - IEnumerable? containers = null, - IEnumerable? compositions = null) => - new() - { - Name = name, - Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), - Key = key ?? Guid.NewGuid(), - ContainerKey = parentKey, - Properties = propertyTypes ?? Enumerable.Empty(), - Containers = containers ?? Enumerable.Empty(), - Compositions = compositions ?? Enumerable.Empty(), - IsElement = isElement - }; - - private ContentTypeUpdateModel CreateUpdateModel( - string name = "Test", - string? alias = null, - bool isElement = false, - IEnumerable? propertyTypes = null, - IEnumerable? containers = null, - IEnumerable? compositions = null) => - new() - { - Name = name, - Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), - Properties = propertyTypes ?? Enumerable.Empty(), - Containers = containers ?? Enumerable.Empty(), - Compositions = compositions ?? Enumerable.Empty(), - IsElement = isElement - }; - - private ContentTypePropertyTypeModel CreatePropertyType( - string name = "Title", - string? alias = null, - Guid? key = null, - Guid? containerKey = null, - Guid? dataTypeKey = null) => - new() - { - Name = name, - Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), - Key = key ?? Guid.NewGuid(), - ContainerKey = containerKey, - DataTypeKey = dataTypeKey ?? Constants.DataTypes.Guids.TextstringGuid, - Validation = new PropertyTypeValidation(), - Appearance = new PropertyTypeAppearance(), - }; - - private ContentTypePropertyContainerModel CreateContainer( - string name = "Container", - string type = TabContainerType, - Guid? key = null) => - new() - { - Name = name, - Type = type, - Key = key ?? Guid.NewGuid(), - }; } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTestsBase.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTestsBase.cs new file mode 100644 index 0000000000..98af01c082 --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTestsBase.cs @@ -0,0 +1,183 @@ +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services.ContentTypeEditing; +using Umbraco.Cms.Tests.Common.Testing; +using Umbraco.Cms.Tests.Integration.Testing; + +namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; + +[TestFixture] +[UmbracoTest( + Database = UmbracoTestOptions.Database.NewSchemaPerTest, + PublishedRepositoryEvents = true, + WithApplication = true)] +public abstract class ContentTypeEditingServiceTestsBase : UmbracoIntegrationTest +{ + protected IContentTypeEditingService ContentTypeEditingService => GetRequiredService(); + + protected IMediaTypeEditingService MediaTypeEditingService => GetRequiredService(); + + protected IContentTypeService ContentTypeService => GetRequiredService(); + + protected IMediaTypeService MediaTypeService => GetRequiredService(); + + protected const string TabContainerType = "Tab"; + + protected const string GroupContainerType = "Group"; + + protected ContentTypeCreateModel ContentTypeCreateModel( + string name = "Test", + string? alias = null, + Guid? key = null, + bool isElement = false, + Guid? containerKey = null, + IEnumerable? propertyTypes = null, + IEnumerable? containers = null, + IEnumerable? compositions = null) + { + var model = CreateContentEditingModel( + name, + alias, + isElement, + propertyTypes, + containers, + compositions); + model.Key = key ?? Guid.NewGuid(); + model.Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name); + model.ContainerKey = containerKey; + return model; + } + + protected MediaTypeCreateModel MediaTypeCreateModel( + string name = "Test", + string? alias = null, + Guid? key = null, + bool isElement = false, + Guid? containerKey = null, + IEnumerable? propertyTypes = null, + IEnumerable? containers = null, + IEnumerable? compositions = null) + { + var model = CreateContentEditingModel( + name, + alias, + isElement, + propertyTypes, + containers, + compositions); + model.Key = key ?? Guid.NewGuid(); + model.Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name); + model.ContainerKey = containerKey; + return model; + } + + protected ContentTypeUpdateModel ContentTypeUpdateModel( + string name = "Test", + string? alias = null, + bool isElement = false, + IEnumerable? propertyTypes = null, + IEnumerable? containers = null, + IEnumerable? compositions = null) + => CreateContentEditingModel( + name, + alias, + isElement, + propertyTypes, + containers, + compositions); + + protected MediaTypeUpdateModel MediaTypeUpdateModel( + string name = "Test", + string? alias = null, + bool isElement = false, + IEnumerable? propertyTypes = null, + IEnumerable? containers = null, + IEnumerable? compositions = null) + => CreateContentEditingModel( + name, + alias, + isElement, + propertyTypes, + containers, + compositions); + + protected ContentTypePropertyTypeModel ContentTypePropertyTypeModel( + string name = "Title", + string? alias = null, + Guid? key = null, + Guid? containerKey = null, + Guid? dataTypeKey = null) + => CreatePropertyType(name, alias, key, containerKey, dataTypeKey); + + protected MediaTypePropertyTypeModel MediaTypePropertyTypeModel( + string name = "Title", + string? alias = null, + Guid? key = null, + Guid? containerKey = null, + Guid? dataTypeKey = null) + => CreatePropertyType(name, alias, key, containerKey, dataTypeKey); + + protected ContentTypePropertyContainerModel ContentTypePropertyContainerModel( + string name = "Container", + string type = TabContainerType, + Guid? key = null) + => CreateContainer(name, type, key); + + protected MediaTypePropertyContainerModel MediaTypePropertyContainerModel( + string name = "Container", + string type = TabContainerType, + Guid? key = null) + => CreateContainer(name, type, key); + + private TModel CreateContentEditingModel( + string name, + string? alias = null, + bool isElement = false, + IEnumerable? propertyTypes = null, + IEnumerable? containers = null, + IEnumerable? compositions = null) + where TModel : ContentTypeEditingModelBase, new() + where TPropertyType : PropertyTypeModelBase + where TPropertyTypeContainer : PropertyTypeContainerModelBase + => new() + { + Name = name, + Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), + Properties = propertyTypes ?? Enumerable.Empty(), + Containers = containers ?? Enumerable.Empty(), + Compositions = compositions ?? Enumerable.Empty(), + IsElement = isElement + }; + + private TModel CreatePropertyType( + string name, + string? alias = null, + Guid? key = null, + Guid? containerKey = null, + Guid? dataTypeKey = null) + where TModel : PropertyTypeModelBase, new() + => new() + { + Name = name, + Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), + Key = key ?? Guid.NewGuid(), + ContainerKey = containerKey, + DataTypeKey = dataTypeKey ?? Constants.DataTypes.Guids.TextstringGuid, + Validation = new PropertyTypeValidation(), + Appearance = new PropertyTypeAppearance(), + }; + + private TModel CreateContainer( + string name, + string type = TabContainerType, + Guid? key = null) + where TModel : PropertyTypeContainerModelBase, new() + => new() + { + Name = name, + Type = type, + Key = key ?? Guid.NewGuid(), + }; +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Create.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Create.cs index 66d4f30838..b9d0027f2b 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Create.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Create.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; @@ -9,7 +10,7 @@ public partial class MediaTypeEditingServiceTests [Test] public async Task Can_Create_With_All_Basic_Settings() { - var createModel = CreateCreateModel("Test Media Type", "testMediaType"); + var createModel = MediaTypeCreateModel("Test Media Type", "testMediaType"); createModel.Description = "This is the Test description"; createModel.Icon = "icon icon-something"; createModel.AllowedAsRoot = true; @@ -40,7 +41,7 @@ public partial class MediaTypeEditingServiceTests var container = containerResult.Result?.Entity; Assert.IsNotNull(container); - var createModel = CreateCreateModel("Test", "test", parentKey: container.Key); + var createModel = MediaTypeCreateModel("Test", "test", containerKey: container.Key); var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); Assert.IsTrue(result.Success); @@ -53,11 +54,11 @@ public partial class MediaTypeEditingServiceTests [Test] public async Task Can_Create_With_Properties_In_A_Container() { - var createModel = CreateCreateModel("Test", "test"); - var container = CreateContainer(); + var createModel = MediaTypeCreateModel("Test", "test"); + var container = MediaTypePropertyContainerModel(); createModel.Containers = new[] { container }; - var propertyType = CreatePropertyType(name: "Test Property", alias: "testProperty", containerKey: container.Key); + var propertyType = MediaTypePropertyTypeModel(name: "Test Property", alias: "testProperty", containerKey: container.Key); createModel.Properties = new[] { propertyType }; var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -78,15 +79,15 @@ public partial class MediaTypeEditingServiceTests [Test] public async Task Can_Create_As_Child() { - var parentProperty = CreatePropertyType("Parent Property", "parentProperty"); - var parentModel = CreateCreateModel( + var parentProperty = MediaTypePropertyTypeModel("Parent Property", "parentProperty"); + var parentModel = MediaTypeCreateModel( name: "Parent", propertyTypes: new[] { parentProperty }); var parentResult = await MediaTypeEditingService.CreateAsync(parentModel, Constants.Security.SuperUserKey); Assert.IsTrue(parentResult.Success); - var childProperty = CreatePropertyType("Child Property", "childProperty"); + var childProperty = MediaTypePropertyTypeModel("Child Property", "childProperty"); var parentKey = parentResult.Result!.Key; Composition[] composition = { @@ -96,7 +97,7 @@ public partial class MediaTypeEditingServiceTests }, }; - var childModel = CreateCreateModel( + var childModel = MediaTypeCreateModel( name: "Child", propertyTypes: new[] { childProperty }, compositions: composition); @@ -114,4 +115,72 @@ public partial class MediaTypeEditingServiceTests Assert.IsTrue(mediaType.CompositionPropertyTypes.Any(x => x.Alias == parentProperty.Alias)); Assert.IsTrue(mediaType.CompositionPropertyTypes.Any(x => x.Alias == childProperty.Alias)); } + + [Test] + public async Task Can_Create_Composite() + { + var compositionBase = MediaTypeCreateModel("Composition Base"); + + // Let's add a property to ensure that it passes through + var container = MediaTypePropertyContainerModel(); + compositionBase.Containers = new[] { container }; + + var compositionProperty = MediaTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: container.Key); + compositionBase.Properties = new[] { compositionProperty }; + + var compositionResult = await MediaTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); + Assert.IsTrue(compositionResult.Success); + var compositionType = compositionResult.Result; + + // Create media type using the composition + var createModel = MediaTypeCreateModel( + compositions: new[] + { + new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, + } + ); + + var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); + var mediaType = await MediaTypeService.GetAsync(result.Result!.Key); + + Assert.Multiple(() => + { + Assert.AreEqual(1, mediaType.ContentTypeComposition.Count()); + Assert.AreEqual(compositionType.Key, mediaType.ContentTypeComposition.First().Key); + Assert.AreEqual(1, compositionType.CompositionPropertyGroups.Count()); + Assert.AreEqual(container.Key, compositionType.CompositionPropertyGroups.First().Key); + Assert.AreEqual(1, compositionType.CompositionPropertyTypes.Count()); + Assert.AreEqual(compositionProperty.Key, compositionType.CompositionPropertyTypes.First().Key); + }); + } + + [Test] + public async Task Cannot_Create_Composite_With_ContentType() + { + var compositionBase = ContentTypeCreateModel("Composition Base"); + + // Let's add a property to ensure that it passes through + var container = ContentTypePropertyContainerModel(); + compositionBase.Containers = new[] { container }; + + var compositionProperty = ContentTypePropertyTypeModel("Composition Property", "compositionProperty", containerKey: container.Key); + compositionBase.Properties = new[] { compositionProperty }; + + var compositionResult = await ContentTypeEditingService.CreateAsync(compositionBase, Constants.Security.SuperUserKey); + Assert.IsTrue(compositionResult.Success); + var compositionType = compositionResult.Result; + + // Create media type using the composition + var createModel = MediaTypeCreateModel( + compositions: new[] + { + new Composition { CompositionType = CompositionType.Composition, Key = compositionType.Key, }, + } + ); + + var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + Assert.IsFalse(result.Success); + Assert.AreEqual(ContentTypeOperationStatus.InvalidComposition, result.Status); + } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.GetAvailableCompositions.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.GetAvailableCompositions.cs new file mode 100644 index 0000000000..3717c42280 --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.GetAvailableCompositions.cs @@ -0,0 +1,91 @@ +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; + +/// +/// These tests are enough to test that we are not mixing content and media types when looking for compositions, +/// even though those share a base implementation. +/// For a more detailed test suite on compositions, check . +/// +public partial class MediaTypeEditingServiceTests +{ + [Test] + public async Task Can_Get_Available_Compositions_Only_From_Media_Type_Key() + { + var container1 = MediaTypePropertyContainerModel(); + var propertyType1 = MediaTypePropertyTypeModel("Property 1", "property1", containerKey: container1.Key); + var mediaType1 = MediaTypeCreateModel( + "Media type 1", + "mediaType1", + propertyTypes: new[] { propertyType1 }, + containers: new[] { container1 }); + + var result1 = await MediaTypeEditingService.CreateAsync(mediaType1, Constants.Security.SuperUserKey); + + var container2 = MediaTypePropertyContainerModel(); + var propertyType2 = MediaTypePropertyTypeModel("Property 2", "property2", containerKey: container2.Key); + var mediaType2 = MediaTypeCreateModel( + "Media type 2", + "mediaType2", + propertyTypes: new[] { propertyType2 }, + containers: new[] { container2 }); + + var result2 = await MediaTypeEditingService.CreateAsync(mediaType2, Constants.Security.SuperUserKey); + + var container3 = MediaTypePropertyContainerModel(); + var propertyType3 = MediaTypePropertyTypeModel("Property 3", "property3", containerKey: container3.Key); + var mediaType3 = MediaTypeCreateModel( + "Media type 3", + "mediaType3", + propertyTypes: new[] { propertyType3 }, + containers: new[] { container3 }); + + var result3 = await MediaTypeEditingService.CreateAsync(mediaType3, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await MediaTypeEditingService.GetAvailableCompositionsAsync( + result1.Result!.Key, + Enumerable.Empty(), + Enumerable.Empty()); + + // Verify that mediaType2 and mediaType3 are present in available compositions + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result2.Result!.Key && compositionsResult.Allowed)); + Assert.IsTrue(availableCompositions.Any(compositionsResult => + compositionsResult.Composition.Key == result3.Result!.Key && compositionsResult.Allowed)); + } + + [Test] + public async Task Available_Compositions_For_Media_Type_Are_Not_Content_Types() + { + var container1 = MediaTypePropertyContainerModel(); + var propertyType1 = MediaTypePropertyTypeModel("Property 1", "property1", containerKey: container1.Key); + var mediaType = MediaTypeCreateModel( + "Media type", + "mediaType", + propertyTypes: new[] { propertyType1 }, + containers: new[] { container1 }); + + var result1 = await MediaTypeEditingService.CreateAsync(mediaType, Constants.Security.SuperUserKey); + + var container2 = ContentTypePropertyContainerModel(); + var propertyType2 = ContentTypePropertyTypeModel("Property 2", "property2", containerKey: container2.Key); + var contentType = ContentTypeCreateModel( + "Content type", + "contentType", + propertyTypes: new[] { propertyType2 }, + containers: new[] { container2 }); + + var result2 = await ContentTypeEditingService.CreateAsync(contentType, Constants.Security.SuperUserKey); + + IEnumerable availableCompositions = + await MediaTypeEditingService.GetAvailableCompositionsAsync( + result1.Result!.Key, + Enumerable.Empty(), + Enumerable.Empty()); + + Assert.IsFalse(availableCompositions.Any(compositionsResult => compositionsResult.Composition.Key == result2.Result!.Key)); + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Update.cs index d9cc936f21..a2ea9ad916 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.Update.cs @@ -9,10 +9,10 @@ public partial class MediaTypeEditingServiceTests [Test] public async Task Can_Update_All_Basic_Settings() { - var createModel = CreateCreateModel("Test Media Type", "testMediaType"); + var createModel = MediaTypeCreateModel("Test Media Type", "testMediaType"); var mediaType = (await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test updated", "testUpdated"); + var updateModel = MediaTypeUpdateModel("Test updated", "testUpdated"); updateModel.Description = "This is the Test description updated"; updateModel.Icon = "icon icon-something-updated"; updateModel.AllowedAsRoot = false; @@ -36,11 +36,11 @@ public partial class MediaTypeEditingServiceTests [Test] public async Task Can_Add_Allowed_Types() { - var allowedOne = (await MediaTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; - var allowedTwo = (await MediaTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; - var allowedThree = (await MediaTypeEditingService.CreateAsync(CreateCreateModel("Allowed Three", "allowedThree"), Constants.Security.SuperUserKey)).Result!; + var allowedOne = (await MediaTypeEditingService.CreateAsync(MediaTypeCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!; + var allowedTwo = (await MediaTypeEditingService.CreateAsync(MediaTypeCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!; + var allowedThree = (await MediaTypeEditingService.CreateAsync(MediaTypeCreateModel("Allowed Three", "allowedThree"), Constants.Security.SuperUserKey)).Result!; - var createModel = CreateCreateModel("Test", "test"); + var createModel = MediaTypeCreateModel("Test", "test"); createModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias), @@ -48,7 +48,7 @@ public partial class MediaTypeEditingServiceTests }; var mediaType = (await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; - var updateModel = CreateUpdateModel("Test", "test"); + var updateModel = MediaTypeUpdateModel("Test", "test"); updateModel.AllowedContentTypes = new[] { new ContentTypeSort(allowedTwo.Key, 20, allowedTwo.Alias), @@ -72,19 +72,19 @@ public partial class MediaTypeEditingServiceTests [Test] public async Task Can_Edit_Properties() { - var createModel = CreateCreateModel("Test", "test"); - var propertyType = CreatePropertyType("Test Property", "testProperty"); + var createModel = MediaTypeCreateModel("Test", "test"); + var propertyType = MediaTypePropertyTypeModel("Test Property", "testProperty"); propertyType.Description = "The description"; createModel.Properties = new[] { propertyType }; var mediaType = (await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!; var originalPropertyTypeKey = mediaType.PropertyTypes.First().Key; - var updateModel = CreateUpdateModel("Test", "test"); - propertyType = CreatePropertyType("Test Property Updated", "testProperty", key: originalPropertyTypeKey); + var updateModel = MediaTypeUpdateModel("Test", "test"); + propertyType = MediaTypePropertyTypeModel("Test Property Updated", "testProperty", key: originalPropertyTypeKey); propertyType.Description = "The updated description"; propertyType.SortOrder = 10; - var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2"); + var propertyType2 = MediaTypePropertyTypeModel("Test Property 2", "testProperty2"); propertyType2.Description = "The description 2"; propertyType2.SortOrder = 5; updateModel.Properties = new[] { propertyType, propertyType2 }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.cs index 575912dd7d..377a5f7ece 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaTypeEditingServiceTests.cs @@ -1,92 +1,9 @@ -using NUnit.Framework; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Models.ContentTypeEditing; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Services.ContentTypeEditing; -using Umbraco.Cms.Tests.Common.Testing; -using Umbraco.Cms.Tests.Integration.Testing; -using PropertyTypeValidation = Umbraco.Cms.Core.Models.ContentTypeEditing.PropertyTypeValidation; - -namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; +namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; /// /// Tests for the media type editing service. Please notice that a lot of functional test is covered by the content type /// editing service tests, since these services share the same base implementation. /// -[TestFixture] -[UmbracoTest( - Database = UmbracoTestOptions.Database.NewSchemaPerTest, - PublishedRepositoryEvents = true, - WithApplication = true)] -public partial class MediaTypeEditingServiceTests : UmbracoIntegrationTest +public partial class MediaTypeEditingServiceTests : ContentTypeEditingServiceTestsBase { - private IMediaTypeEditingService MediaTypeEditingService => GetRequiredService(); - - private IMediaTypeService MediaTypeService => GetRequiredService(); - - private const string TabContainerType = "Tab"; - - private const string GroupContainerType = "Group"; - - private MediaTypeCreateModel CreateCreateModel( - string name = "Test", - string? alias = null, - Guid? key = null, - Guid? parentKey = null, - IEnumerable? propertyTypes = null, - IEnumerable? containers = null, - IEnumerable? compositions = null) => - new() - { - Name = name, - Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), - Key = key ?? Guid.NewGuid(), - ParentKey = parentKey, - Properties = propertyTypes ?? Enumerable.Empty(), - Containers = containers ?? Enumerable.Empty(), - Compositions = compositions ?? Enumerable.Empty(), - }; - - private MediaTypeUpdateModel CreateUpdateModel( - string name = "Test", - string? alias = null, - IEnumerable? propertyTypes = null, - IEnumerable? containers = null, - IEnumerable? compositions = null) => - new() - { - Name = name, - Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), - Properties = propertyTypes ?? Enumerable.Empty(), - Containers = containers ?? Enumerable.Empty(), - Compositions = compositions ?? Enumerable.Empty() - }; - - private MediaTypePropertyTypeModel CreatePropertyType( - string name = "Title", - string? alias = null, - Guid? key = null, - Guid? containerKey = null, - Guid? dataTypeKey = null) => - new() - { - Name = name, - Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name), - Key = key ?? Guid.NewGuid(), - ContainerKey = containerKey, - DataTypeKey = dataTypeKey ?? Constants.DataTypes.Guids.TextstringGuid, - Validation = new PropertyTypeValidation(), - Appearance = new PropertyTypeAppearance(), - }; - - private MediaTypePropertyContainerModel CreateContainer( - string name = "Container", - string type = TabContainerType, - Guid? key = null) => - new() - { - Name = name, - Type = type, - Key = key ?? Guid.NewGuid(), - }; } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index f02179e159..352fa7d742 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -106,12 +106,18 @@ ContentTypeEditingServiceTests.cs + + ContentTypeEditingServiceTests.cs + ContentTypeEditingServiceTests.cs MediaTypeEditingServiceTests.cs + + MediaTypeEditingServiceTests.cs + MediaTypeEditingServiceTests.cs