Skip to content

Commit 64da55a

Browse files
authored
Merge branch 'umbraco:main' into main
2 parents b4b97fc + b7e39f9 commit 64da55a

File tree

5,336 files changed

+195090
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

5,336 files changed

+195090
-438
lines changed

13/umbraco-cms/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@
353353
* [TextService](reference/management/services/textservice.md)
354354
* [ContentService](reference/management/services/contentservice/README.md)
355355
* [Create content programmatically](reference/management/services/contentservice/create-content-programmatically.md)
356+
* [Publish content programmatically](reference/management/services/contentservice/publish-content-programmatically.md)
356357
* [ContentTypeService](reference/management/services/contenttypeservice/README.md)
357358
* [Retrieving content types](reference/management/services/contenttypeservice/retrieving-content-type-containers.md)
358359
* [Retrieving content types](reference/management/services/contenttypeservice/retrieving-content-types.md)

13/umbraco-cms/reference/configuration/contentsettings.md

+17-8
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ The following snippet will give an overview of the keys and values in the conten
4747
"PreviewBadge": "<![CDATA[<b>My HTML here</b>]]>",
4848
"ResolveUrlsFromTextString": false,
4949
"ShowDeprecatedPropertyEditors": false,
50-
"ShowDomainWarnings": true
50+
"ShowDomainWarnings": true,
51+
"ShowUnroutableContentWarnings": true
5152
}
5253
}
5354
}
@@ -174,15 +175,23 @@ This setting is used for controlling whether or not the Data Types marked as obs
174175

175176
By default this is set to `false`. To make the obsolete data types visible in the dropdown change the value to `true`.
176177

177-
### Show Domain Warnings
178+
### Show domain warnings
178179

179180
If you do not configure Domains for each language in a multilingual site then every time you publish your content you get this warning:
180181

181182
`Content published: Domains are not configured for multilingual site, please contact an administrator, see log for more information.`
182183

183184
If you have a use case for not setting the domains, you can set this setting **ShowDomainWarnings** to `false` to stop the warning from displaying.
184185

185-
## ContentVersionCleanupPolicy
186+
### Show unroutable content warnings
187+
188+
If your routing setup leads to more than one document having the same URL, on publish a warning will be displayed:
189+
190+
`Content published: The document does not have a URL, possibly due to a naming collision with another document. More details can be found under Info.`
191+
192+
To suppress these warnings, set this option to `false`.
193+
194+
## Content version cleanup policy
186195

187196
The global settings for the scheduled job which cleans historic content versions. These settings can be overridden per Document Type.
188197

@@ -200,19 +209,19 @@ See [Content Version Cleanup](../../fundamentals/data/content-version-cleanup.md
200209

201210
To retain only the current draft and published version, set both the "keep" settings values to 0. The next time the scheduled job runs (hourly) all non-current versions (except those marked "prevent cleanup") will be removed.
202211

203-
### EnableCleanup
212+
### Enable cleanup
204213

205214
When set to `true`, a scheduled job will delete historic content versions that are not retained according to the policy every hour.
206215

207216
When set to `false`, the scheduled job will not delete any content versions, regardless of any overridden settings for a Document Type.
208217

209218
The dotnet new template provides an `appsettings.json` file with the default value set to `true` for all sites.
210219

211-
### KeepAllVersionsNewerThanDays
220+
### Keep all versions newer than days
212221

213222
All versions that fall in this period will be kept.
214223

215-
### KeepLatestVersionPerDayForDays
224+
### Keep latest version per day for days
216225

217226
For content versions that fall in this period, the most recent version for each day is kept. All previous versions for that day are removed unless marked as preventCleanup.
218227

@@ -237,11 +246,11 @@ This section is used for managing how Umbraco handles images, allowed attributes
237246

238247
Let's break it down.
239248

240-
### ImageFileTypes
249+
### Image file types
241250

242251
This is a separated list of accepted image formats
243252

244-
### AutoFillImageProperties
253+
### Auto fill image properties
245254

246255
You can define what properties should be automatically updated when an image is being uploaded. This means that if you decide to rename the default **umbracoWidth** and **umbracoHeight** properties the values in **`"WidthFieldAlias"`** and **`"HeightFieldAlias"`** need to be updated. This needs to happen in order to automatically populate the values when the image is being uploaded.
247256

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Publishing content programmatically
2+
3+
The ContentService is also used for publishing operations.
4+
5+
The following example shows a page being published with all descendants.
6+
7+
```csharp
8+
using Umbraco.Cms.Core.Models;
9+
using Umbraco.Cms.Core.Services;
10+
11+
namespace Umbraco.Cms.Web.UI.Custom;
12+
13+
public class PublishContentDemo
14+
{
15+
private readonly IContentService _contentService;
16+
17+
public PublishContentDemo(IContentService contentService) => _contentService = contentService;
18+
19+
public void Publish(Guid key)
20+
{
21+
IContent? content = _contentService.GetById(key)
22+
?? throw new InvalidOperationException($"Could not find content with key: {key}.");
23+
24+
_contentService.SaveAndPublishBranch(content, PublishBranchFilter.Default);
25+
}
26+
}
27+
```
28+
29+
The `PublishBranchFilter` option can include one or more of the following flags:
30+
31+
- `Default` - publishes existing published content with pending changes.
32+
- `IncludeUnpublished` - publishes unpublished content and existing published content with pending changes.
33+
- `ForceRepublish` - publishes existing published content with or without pending changes.
34+
- `All` - combines `IncludeUnpublished` and `ForceRepublish`.
35+

13/umbraco-cms/tutorials/editors-manual/getting-started-with-umbraco/creating-saving-and-publishing-content.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ To publish the node with descendants, follow these steps:
6565
3. Select **Publish with descendants**.
6666

6767
![Publish with descendants](../../../../../10/umbraco-cms/tutorials/editors-manual/getting-started-with-umbraco/images/Publish-with-descendants-v9.png)
68-
4. Toggle the option to **Include unpublished content items** if you wish to. This option includes all unpublished content items for the selected page and the available linked pages.
69-
68+
4. Toggle the option to **Include unpublished content items** if you wish to. This option includes all unpublished content items for the selected page and the descendant pages.
7069
![Publish with descendants](../../../../../10/umbraco-cms/tutorials/editors-manual/getting-started-with-umbraco/images/Publish-with-descendants2-v9.png)
7170

7271
#### 3: Unpublish

13/umbraco-engage/developers/analytics/location.md

+7
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,10 @@ If the pageviews contain location information, the table with countries is displ
106106
<figure><img src="../../.gitbook/assets/image (1) (4).png" alt="Location table - missing data error"><figcaption><p>Location table with data</p></figcaption></figure>
107107

108108
From the country, you can drill down to the city. This will then filter the displayed graph and table data to only display session and pageview information for the selected country. Even though Umbraco Engage does support the storage for county and province, the UI only supports displaying data by country and city.
109+
110+
### Community package
111+
112+
A community package called "[Engage LocationHeaders](https://github.com/hjaltedaniel-umbraco/Umbraco.Community.Engage.LocationHeaders)" is available. It's a lightweight package that enriches analytics and segmentation data with location information extracted from the HTTP headers, based on the sample code above.
113+
114+
The package is designed to work out-of-the-box on **Umbraco Cloud**, using location headers automatically injected by services like **Cloudflare** or **Azure Front Door**. This allows Umbraco Engage to tap into geographic information such as **country**, **region**, and **city**, without the need for client-side geolocation or third-party services.
115+

15/umbraco-cms/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@
362362
* [Determining if an entity is new](reference/notifications/determining-new-entity.md)
363363
* [MediaService Notifications Example](reference/notifications/mediaservice-notifications.md)
364364
* [MemberService Notifications Example](reference/notifications/memberservice-notifications.md)
365+
* [UserService Notifications Example](reference/notifications/userservice-notifications.md)
365366
* [Sending Allowed Children Notification](reference/notifications/sendingallowedchildrennotifications.md)
366367
* [Umbraco Application Lifetime Notifications](reference/notifications/umbracoapplicationlifetime-notifications.md)
367368
* [EditorModel Notifications](reference/notifications/editormodel-notifications/README.md)

15/umbraco-cms/customizing/extending-overview/extension-registry/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ The extension registry is a global registry that can be accessed and changed at
1414

1515
Each Extension Manifest has to declare its type, this is used to determine where it hooks into the system. It also looks at what data is required to declare within it.
1616

17-
## [Replace, Exclude or Unregistere](./#replace-exclude-or-unregistere)
17+
## [Replace, Exclude, or Unregister](replace-exclude-or-unregister.md)
1818

1919
Once you understand how to declare your own, you may want to replace or remove existing.

15/umbraco-cms/customizing/extending-overview/extension-registry/replace-exclude-or-unregister.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ UmbExtensionRegistry.exclude('Umb.WorkspaceAction.Document.SaveAndPreview');
5454

5555
## Unregister
5656

57-
You can also choose to unregister an extension, this is only preferred if you registered the extension and are in control of the flow. If its not your Extension please seek to use the `Overwrites` or `Exclude` feature.
57+
You can also choose to unregister an extension, this is only preferred if you registered the extension and are in control of the flow. If it's not your Extension please seek to use the `Overwrites` or `Exclude` feature.
5858

5959
```typescript
60-
import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extension-api';
60+
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
6161

62-
UmbExtensionRegistry.unregister('My.WorkspaceAction.AutoFillWithUnicorns');
62+
umbExtensionsRegistry.unregister('My.WorkspaceAction.AutoFillWithUnicorns');
6363
```
6464

6565
This will not prevent the Extension from being registered again.

15/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/rich-text-editor/extensions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export const manifests: Array<UmbExtensionManifest> = [
7070
{
7171
type: 'tiptapExtension',
7272
kind: 'button',
73-
alias: 'My Highlight Tiptap Extension',
74-
name: 'My.Tiptap.Highlight',
73+
alias: 'My.Tiptap.Highlight',
74+
name: 'My Highlight Tiptap Extension',
7575
api: () => import('./highlight.tiptap-api.js'),
7676
meta:{
7777
icon: "icon-thumbnail-list",

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

+64-11
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
```

15/umbraco-cms/reference/notifications/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -285,5 +285,6 @@ Below you can find some articles with some examples using Notifications.
285285
* [Hot vs. cold restarts](hot-vs-cold-restarts.md)
286286
* [MediaService Notifications](mediaservice-notifications.md)
287287
* [MemberService Notifications](memberservice-notifications.md)
288+
* [UserService Notifications](userservice-notifications.md)
288289
* [Sending Allowed Children Notification](sendingallowedchildrennotifications.md)
289290
* [Umbraco Application Lifetime Notifications](umbracoapplicationlifetime-notifications.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
description: Example of how to use a UserService Notification
3+
---
4+
5+
# UserService Notifications
6+
7+
The UserService implements `IUserService` and provides access to operations involving `IUser`.
8+
9+
The following example illustrates how to cancel the password reset feature for a given set of users.
10+
11+
## Usage
12+
13+
```csharp
14+
using Umbraco.Cms.Core.Events;
15+
using Umbraco.Cms.Core.Notifications;
16+
17+
namespace MySite;
18+
19+
public class UserPasswordResettingNotificationHandler : INotificationHandler<UserPasswordResettingNotification>
20+
{
21+
public void Handle(UserPasswordResettingNotification notification)
22+
{
23+
if (notification.User.Name?.Contains("Eddie") ?? false)
24+
{
25+
notification.CancelOperation(new EventMessage("fail", "Can't reset password for users with name containing 'Eddie'"));
26+
}
27+
}
28+
}
29+
```

0 commit comments

Comments
 (0)