Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Controllers.Template;
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.DocumentType;

[ApiVersion("1.0")]
public class CreateDocumentTypeTemplateController : DocumentTypeControllerBase
{
private readonly IContentTypeService _contentTypeService;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;

public CreateDocumentTypeTemplateController(
IContentTypeService contentTypeService,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
{
_contentTypeService = contentTypeService;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
}

[HttpPost("{id:guid}/template")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateTemplate(
CancellationToken cancellationToken,
Guid id,
CreateDocumentTypeTemplateRequestModel requestModel)
{
Attempt<Guid?, ContentTypeOperationStatus> result = await _contentTypeService.CreateTemplateAsync(
id,
requestModel.Name,
requestModel.Alias,
requestModel.IsDefault,
CurrentUserKey(_backOfficeSecurityAccessor));

return result.Success
? CreatedAtId<ByKeyTemplateController>(controller => nameof(controller.ByKey), result.Result!.Value)
: OperationStatusResult(result.Status);
}
}
156 changes: 155 additions & 1 deletion src/Umbraco.Cms.Api.Management/OpenApi.json
Original file line number Diff line number Diff line change
Expand Up @@ -5661,6 +5661,137 @@
]
}
},
"/umbraco/management/api/v1/document-type/{id}/template": {
"post": {
"tags": [
"Document Type"
],
"operationId": "PostDocumentTypeByIdTemplate",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/CreateDocumentTypeTemplateRequestModel"
}
]
}
},
"text/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/CreateDocumentTypeTemplateRequestModel"
}
]
}
},
"application/*+json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/CreateDocumentTypeTemplateRequestModel"
}
]
}
}
}
},
"responses": {
"201": {
"description": "Created",
"headers": {
"Umb-Generated-Resource": {
"description": "Identifier of the newly created resource",
"schema": {
"type": "string",
"description": "Identifier of the newly created resource"
}
},
"Location": {
"description": "Location of the newly created resource",
"schema": {
"type": "string",
"description": "Location of the newly created resource",
"format": "uri"
}
},
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
}
},
"400": {
"description": "Bad Request",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
},
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/ProblemDetails"
}
]
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
},
"403": {
"description": "The authenticated user does not have access to this resource",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
}
}
},
"security": [
{
"Backoffice-User": [ ]
}
]
}
},
"/umbraco/management/api/v1/document-type/allowed-at-root": {
"get": {
"tags": [
Expand Down Expand Up @@ -36304,6 +36435,28 @@
},
"additionalProperties": false
},
"CreateDocumentTypeTemplateRequestModel": {
"required": [
"alias",
"isDefault",
"name"
],
"type": "object",
"properties": {
"alias": {
"minLength": 1,
"type": "string"
},
"name": {
"minLength": 1,
"type": "string"
},
"isDefault": {
"type": "boolean"
}
},
"additionalProperties": false
},
"CreateFolderRequestModel": {
"required": [
"name"
Expand Down Expand Up @@ -38444,7 +38597,8 @@
"type": "boolean"
},
"allowNonExistingSegmentsCreation": {
"type": "boolean"
"type": "boolean",
"deprecated": true
}
},
"additionalProperties": false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;

namespace Umbraco.Cms.Api.Management.ViewModels.DocumentType;

public class CreateDocumentTypeTemplateRequestModel
{
[Required]
public required string Alias { get; set; }

[Required]
public required string Name { get; set; }

public bool IsDefault { get; set; }
}
84 changes: 82 additions & 2 deletions src/Umbraco.Core/Services/ContentTypeService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
Expand All @@ -8,6 +10,7 @@
using Umbraco.Cms.Core.Services.Changes;
using Umbraco.Cms.Core.Services.Filters;
using Umbraco.Cms.Core.Services.Locking;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Core.Services;

Expand All @@ -16,6 +19,8 @@
/// </summary>
public class ContentTypeService : ContentTypeServiceBase<IContentTypeRepository, IContentType>, IContentTypeService
{
private readonly ITemplateService _templateService;

public ContentTypeService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
Expand All @@ -27,19 +32,52 @@
IEntityRepository entityRepository,
IEventAggregator eventAggregator,
IUserIdKeyResolver userIdKeyResolver,
ContentTypeFilterCollection contentTypeFilters)
ContentTypeFilterCollection contentTypeFilters,
ITemplateService templateService)
: base(
provider,
loggerFactory,
eventMessagesFactory,
repository,
auditRepository,
entityContainerRepository,
entityRepository,
eventAggregator,
userIdKeyResolver,
contentTypeFilters) =>
contentTypeFilters)
{
_templateService = templateService;
ContentService = contentService;
}

Check warning on line 51 in src/Umbraco.Core/Services/ContentTypeService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Code Duplication

The module contains 2 functions with similar structure: ContentTypeService,ContentTypeService. Avoid duplicated, aka copy-pasted, code inside the module. More duplication lowers the code health.

[Obsolete("Use the non-obsolete constructor. Scheduled for removal in Umbraco 19.")]
public ContentTypeService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
IEventMessagesFactory eventMessagesFactory,
IContentService contentService,
IContentTypeRepository repository,
IAuditRepository auditRepository,
IDocumentTypeContainerRepository entityContainerRepository,
IEntityRepository entityRepository,
IEventAggregator eventAggregator,
IUserIdKeyResolver userIdKeyResolver,
ContentTypeFilterCollection contentTypeFilters)
: this(
provider,
loggerFactory,
eventMessagesFactory,
contentService,
repository,
auditRepository,
entityContainerRepository,
entityRepository,
eventAggregator,
userIdKeyResolver,
contentTypeFilters,
StaticServiceProvider.Instance.GetRequiredService<ITemplateService>())
{
}

protected override int[] ReadLockIds => ContentTypeLocks.ReadLockIds;

Expand Down Expand Up @@ -106,6 +144,48 @@
return contentTypes;
}

/// <inheritdoc />
public async Task<Attempt<Guid?, ContentTypeOperationStatus>> CreateTemplateAsync(
Guid contentTypeKey,
string templateName,
string templateAlias,
bool isDefaultTemplate,
Guid userKey)
{
IContentType? contentType = await GetAsync(contentTypeKey);
if (contentType is null)
{
return Attempt<Guid?, ContentTypeOperationStatus>.Fail(ContentTypeOperationStatus.NotFound);
}

Attempt<ITemplate?, TemplateOperationStatus> templateResult =
await _templateService.CreateForContentTypeAsync(templateName, templateAlias, contentType.Alias, userKey);
if (templateResult.Success is false)
{
return Attempt<Guid?, ContentTypeOperationStatus>.Fail(
templateResult.Status switch
{
TemplateOperationStatus.CancelledByNotification => ContentTypeOperationStatus
.CancelledByNotification,
TemplateOperationStatus.InvalidAlias => ContentTypeOperationStatus.InvalidAlias,
_ => ContentTypeOperationStatus.Unknown,
});
}

ITemplate template = templateResult.Result!;
contentType.AllowedTemplates = [..contentType.AllowedTemplates ?? [], template];
if (isDefaultTemplate)
{
contentType.DefaultTemplateId = template.Id;
}

Attempt<ContentTypeOperationStatus> updateContentTypeResult = await UpdateAsync(contentType, userKey);

return updateContentTypeResult.Success
? Attempt<Guid?, ContentTypeOperationStatus>.Succeed(ContentTypeOperationStatus.Success, template.Key)
: Attempt<Guid?, ContentTypeOperationStatus>.Fail(updateContentTypeResult.Result);
}

Check warning on line 187 in src/Umbraco.Core/Services/ContentTypeService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Excess Number of Function Arguments

CreateTemplateAsync has 5 arguments, max arguments = 4. This function has too many arguments, indicating a lack of encapsulation. Avoid adding more arguments.

protected override void DeleteItemsOfTypes(IEnumerable<int> typeIds)
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
Expand Down
16 changes: 16 additions & 0 deletions src/Umbraco.Core/Services/IContentTypeService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,20 @@
IEnumerable<int> GetAllContentTypeIds(string[] aliases);

Task<IEnumerable<IContentType>> GetByQueryAsync(IQuery<IContentType> query, CancellationToken cancellationToken) => Task.FromResult(Enumerable.Empty<IContentType>());

/// <summary>
/// Creates a template for the given content type.
/// </summary>
/// <param name="contentTypeKey">The content type key.</param>
/// <param name="templateName">The name of the template to create.</param>
/// <param name="templateAlias">The alias of the template to create.</param>
/// <param name="isDefaultTemplate">Whether to set the template as the default template for the content type.</param>
/// <param name="userKey">The key of the user performing the operation.</param>
/// <returns>An attempt containing the template's key if successful, or an error status if not.</returns>
Task<Attempt<Guid?, ContentTypeOperationStatus>> CreateTemplateAsync(
Guid contentTypeKey,
string templateName,
string templateAlias,
bool isDefaultTemplate,
Guid userKey) => throw new NotImplementedException();

Check warning on line 51 in src/Umbraco.Core/Services/IContentTypeService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Excess Number of Function Arguments

CreateTemplateAsync has 5 arguments, max arguments = 4. This function has too many arguments, indicating a lack of encapsulation. Avoid adding more arguments.
}
Loading
Loading