-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Document type references: Backend implementation of endpoints and services #20300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a new feature to track document type references across the Umbraco CMS system. The implementation provides backend services and API endpoints to help users understand dependencies before deleting document types.
- Implements service layer for tracking three types of document type references: documents using a document type, document types inheriting from another, and data types (block list/grid/rich text) referencing element types
- Adds repository methods for querying document and content type relationships
- Creates API controllers with pagination support for exposing reference information via REST endpoints
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
File | Description |
---|---|
ContentTypeReferenceServiceTests.cs | Integration tests covering all three reference scenarios with multiple block editor types |
DocumentRepository.cs | Repository method to find documents by document type key using SQL joins |
DataTypeRepository.cs | Repository method to find block editors referencing content types by parsing configurations |
ContentTypeRepository.cs | Repository method to find child content types using composition relationships |
IContentTypeReferenceService.cs | Service interface defining three async methods for getting references |
ContentTypeReferenceService.cs | Service implementation coordinating repository calls within database scopes |
IDocumentRepository.cs | Interface extension adding document reference query method |
IDataTypeRepository.cs | Interface extension adding block editor reference query method |
IContentTypeRepository.cs | Interface extension adding child content type query method |
UmbracoBuilder.cs | Dependency injection registration for the new service |
ReferencedByDocumentTypeDocumentTypeController.cs | API controller for document types that inherit from a given type |
ReferencedByDocumentDocumentTypeController.cs | API controller for documents using a given document type |
ReferencedByDataTypeDocumentTypeController.cs | API controller for data types referencing a given element type |
tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeReferenceServiceTests.cs
Show resolved
Hide resolved
tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeReferenceServiceTests.cs
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs
Outdated
Show resolved
Hide resolved
…DocumentRepository.cs Co-authored-by: Copilot <[email protected]>
…ContentTypeRepository.cs Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good @Zeegaan. I haven't done a thorough review with testing as I saw Kenn already had 👀on it, but have left a few small formatting suggestions and a question about whether the paging should be introduced on the methods where you return PagedModel
but don't currently accept skip
and take
.
/// </summary> | ||
bool RecycleBinSmells(); | ||
|
||
PagedModel<Guid> GetReferencingDocumentsByDocumentTypeKey(Guid documentTypeKey) => throw new NotImplementedException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have the skip
and take
parameters? Maybe in practice it's fine to get all, but it feels a little odd to return PagedModel
without them.
{ | ||
using ICoreScope scope = _coreScopeProvider.CreateCoreScope(); | ||
|
||
PagedModel<Guid> keys = _contentTypeRepository.GetChildren(key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this will get the inheriting document types - i.e. the children. But should it also get document types that are use the provided document type key as a composition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What @AndyButland said. Also, it applies to all descendants, not just immediate children.
Historically we've "just" loaded all content types and handled these kind of reference detection/validation in memory, from the notion that there really isn't that many content types for it to be a problem. See for example GetAvailableCompositeContentTypes(), which is used to figure out applicable content types available for composition given certain filtering requirements. It expects allContentTypes
.
Constants.PropertyEditors.Aliases.BlockList, | ||
Constants.PropertyEditors.Aliases.RichText, | ||
}; | ||
// Get All contentTypes where isContainer (list view enabled) is set to true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Get All contentTypes where isContainer (list view enabled) is set to true | |
// Get All contentTypes where isContainer (list view enabled) is set to true |
.From<DataTypeDto>() | ||
.InnerJoin<NodeDto>() | ||
.On<DataTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId) | ||
.WhereIn<DataTypeDto>(n => n.EditorAlias, blockEditorAliases ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.WhereIn<DataTypeDto>(n => n.EditorAlias, blockEditorAliases ); | |
.WhereIn<DataTypeDto>(n => n.EditorAlias, blockEditorAliases); |
case Constants.PropertyEditors.Aliases.BlockGrid: | ||
BlockGridConfiguration? blockGridConfigurations = ConfigurationEditor.ConfigurationAs<BlockGridConfiguration>(dataType.ConfigurationObject); | ||
|
||
if(blockGridConfigurations is null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if(blockGridConfigurations is null) | |
if (blockGridConfigurations is null) |
|
||
IEnumerable<int> GetAllContentTypeIds(string[] aliases); | ||
|
||
PagedModel<Guid> GetChildren(Guid parentKey) => throw new NotImplementedException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this method is necessary ref. the comments in ContentTypeReferenceService
Constants.PropertyEditors.Aliases.BlockGrid, | ||
Constants.PropertyEditors.Aliases.BlockList, | ||
Constants.PropertyEditors.Aliases.RichText, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this is true from a core perspective, it does not take into account that extensions might also reference content types. Specifically custom block editors will do, but in theory - any extension can utilize a content type.
_dataTypeRepository = dataTypeRepository; | ||
} | ||
|
||
public Task<PagedModel<Guid>> GetReferencedDocumentKeysAsync(Guid key, CancellationToken cancellationToken, int skip, int take) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like skip
and take
is ever applied here.
Sql<ISqlContext> sqlContentTypeId = Sql() | ||
.Select<ContentTypeDto>(x => x.NodeId) | ||
.From<ContentTypeDto>() | ||
.InnerJoin<NodeDto>() | ||
.On<ContentTypeDto, NodeDto>((c, n) => c.NodeId == n.NodeId) | ||
.Where<NodeDto>(x => x.UniqueId == documentTypeKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any chance the IIdKeyMap
service could be applied here?
Notes
How to test