Skip to content

Commit de2529f

Browse files
committed
Updated copy and code sample relating to allowed at root and allowed children content type filters
1 parent 7732385 commit de2529f

File tree

1 file changed

+64
-11
lines changed

1 file changed

+64
-11
lines changed

15/umbraco-cms/reference/content-type-filters.md

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Describes how to use Content Type Filters to restrict the allowed content options available to editors.
2+
description: Describes how to use Allowed Content Type Filters to restrict the allowed content options available to editors.
33
---
44

55
# Filtering Allowed Content Types
@@ -23,27 +23,45 @@ There are two methods you can implement:
2323
* One for filtering the content types allowed at the content root
2424
* One for the content types allowed below a given parent node.
2525

26-
If you don't want to filter using one of the two approaches, you can return the provided collection unmodified.
26+
If you don't want to filter using one of the two approaches, you can omit the implementation of that method. The default implementation will return the provided collection unmodified.
2727

2828
### Example Use Case
2929

30-
The following example shows a typical use case. Often websites will have a "Home Page" Document Type which is created at the root. Normally, only one of these is required. You can enforce that using the following Content Type Filter.
30+
The following example shows an illustrative but also typical use case. Often websites will have a "Home Page" Document Type which is created at the root. Normally, only one of these is required. You can enforce that using the following Content Type Filter.
3131

32-
The code below is querying the existing content available at the root. Normally you can create a "Home Page" here, but if one already exists that option is removed:
32+
The code below is querying the existing content available at the root. Normally you can create a "Home Page" here, but if one already exists that option is removed.
33+
34+
It then shows how to limit the allowed children by only permitting a single "Landing Page" under the "Home Page" Document Type.
3335

3436
```csharp
35-
internal class OneHomePageOnlyContentTypeFilter : IContentTypeFilter
37+
using Umbraco.Cms.Core;
38+
using Umbraco.Cms.Core.Composing;
39+
using Umbraco.Cms.Core.Models;
40+
using Umbraco.Cms.Core.Services;
41+
using Umbraco.Cms.Core.Services.Filters;
42+
43+
internal class MyContentTypeFilter : IContentTypeFilter
3644
{
45+
private const string HomePageDocTypeAlias = "homePage";
46+
private const string LandingPageDocTypeAlias = "landingPage";
47+
3748
private readonly IContentService _contentService;
49+
private readonly IContentTypeService _contentTypeService;
50+
private readonly IIdKeyMap _idKeyMap;
3851

39-
public OneHomePageOnlyContentTypeFilter(IContentService contentService) => _contentService = contentService;
52+
public MyContentTypeFilter(IContentService contentService, IContentTypeService contentTypeService, IIdKeyMap idKeyMap)
53+
{
54+
_contentService = contentService;
55+
_contentTypeService = contentTypeService;
56+
_idKeyMap = idKeyMap;
57+
}
4058

4159
public Task<IEnumerable<TItem>> FilterAllowedAtRootAsync<TItem>(IEnumerable<TItem> contentTypes)
4260
where TItem : IContentTypeComposition
4361
{
62+
// Only allow one home page at the root.
4463
var docTypeAliasesToExclude = new List<string>();
4564

46-
const string HomePageDocTypeAlias = "homePage";
4765
var docTypeAliasesAtRoot = _contentService.GetRootContent()
4866
.Select(x => x.ContentType.Alias)
4967
.Distinct()
@@ -57,12 +75,47 @@ internal class OneHomePageOnlyContentTypeFilter : IContentTypeFilter
5775
.Where(x => docTypeAliasesToExclude.Contains(x.Alias) is false));
5876
}
5977

60-
public Task<IEnumerable<ContentTypeSort>> FilterAllowedChildrenAsync(IEnumerable<ContentTypeSort> contentTypes, Guid parentKey)
61-
=> Task.FromResult(contentTypes);
78+
public Task<IEnumerable<ContentTypeSort>> FilterAllowedChildrenAsync(
79+
IEnumerable<ContentTypeSort> contentTypes,
80+
Guid parentContentTypeKey,
81+
Guid? parentContentKey)
82+
{
83+
// Only allow one landing page when under a home page.
84+
if (parentContentKey.HasValue is false)
85+
{
86+
return Task.FromResult(contentTypes);
87+
}
88+
89+
IContentType? docType = _contentTypeService.Get(parentContentTypeKey);
90+
if (docType is null || docType.Alias != HomePageDocTypeAlias)
91+
{
92+
return Task.FromResult(contentTypes);
93+
}
94+
95+
var docTypeAliasesToExclude = new List<string>();
96+
97+
Attempt<int> parentContentIdAttempt = _idKeyMap.GetIdForKey(parentContentKey.Value, UmbracoObjectTypes.Document);
98+
if (parentContentIdAttempt.Success is false)
99+
{
100+
return Task.FromResult(contentTypes);
101+
}
102+
103+
var docTypeAliasesAtFolder = _contentService.GetPagedChildren(parentContentIdAttempt.Result, 0, int.MaxValue, out _)
104+
.Select(x => x.ContentType.Alias)
105+
.Distinct()
106+
.ToList();
107+
if (docTypeAliasesAtFolder.Contains(LandingPageDocTypeAlias))
108+
{
109+
docTypeAliasesToExclude.Add(LandingPageDocTypeAlias);
110+
}
111+
112+
return Task.FromResult(contentTypes
113+
.Where(x => docTypeAliasesToExclude.Contains(x.Alias) is false));
114+
}
62115
}
63116
```
64117

65-
Content Type Filters are registered as a collection, making it possible to have more than one in the solution or an installed package.
118+
Allowed Content Type Filters are registered as a collection, making it possible to have more than one in the solution or an installed package.
66119

67120
The filters need to be registered in a composer:
68121

@@ -72,7 +125,7 @@ public class MyComposer : IComposer
72125
public void Compose(IUmbracoBuilder builder)
73126
{
74127
builder.ContentTypeFilters()
75-
.Append<OneHomePageOnlyContentTypeFilter>();
128+
.Append<MyContentTypeFilter>();
76129
}
77130
}
78131
```

0 commit comments

Comments
 (0)