Skip to content

Commit d8551e4

Browse files
Merge branch 'v9/dev' into v9/contrib
2 parents 373138d + ca5c85e commit d8551e4

File tree

52 files changed

+1214
-203
lines changed

Some content is hidden

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

52 files changed

+1214
-203
lines changed

build/azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ stages:
538538
inputs:
539539
targetType: inline
540540
script: |
541-
choco install docfx --version=2.58.5 -y
541+
choco install docfx --version=2.59.0 -y
542542
if ($lastexitcode -ne 0){
543543
throw ("Error installing DocFX")
544544
}

src/ApiDocs/umbracotemplate/partials/class.tmpl.partial

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
<div class="level{{item.level}}"><span class="xref">{{item.name.0.value}}</span></div>
1616
</div>
1717
{{/inheritance.0}}
18-
<h6><strong>{{__global.namespace}}</strong>:{{namespace}}</h6>
19-
<h6><strong>{{__global.assembly}}</strong>:{{assemblies.0}}.dll</h6>
18+
<h6><strong>{{__global.namespace}}</strong>: {{{namespace.specName.0.value}}}</h6>
19+
<h6><strong>{{__global.assembly}}</strong>: {{assemblies.0}}.dll</h6>
2020
<h5 id="{{id}}_syntax">{{__global.syntax}}</h5>
2121
<div class="codewrapper">
2222
<pre><code class="lang-{{_lang}} hljs">{{syntax.content.0.value}}</code></pre>

src/Umbraco.Core/Configuration/Models/GlobalSettings.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class GlobalSettings
2929
internal const string StaticNoNodesViewPath = "~/umbraco/UmbracoWebsite/NoNodes.cshtml";
3030
internal const string StaticSqlWriteLockTimeOut = "00:00:05";
3131
internal const bool StaticSanitizeTinyMce = false;
32+
internal const int StaticMainDomReleaseSignalPollingInterval = 2000;
3233

3334
/// <summary>
3435
/// Gets or sets a value for the reserved URLs (must end with a comma).
@@ -137,6 +138,26 @@ public class GlobalSettings
137138
/// </summary>
138139
public string MainDomLock { get; set; } = string.Empty;
139140

141+
/// <summary>
142+
/// Gets or sets a value to discriminate MainDom boundaries.
143+
/// <para>
144+
/// Generally the default should suffice but useful for advanced scenarios e.g. azure deployment slot based zero downtime deployments.
145+
/// </para>
146+
/// </summary>
147+
public string MainDomKeyDiscriminator { get; set; } = string.Empty;
148+
149+
/// <summary>
150+
/// Gets or sets the duration (in milliseconds) for which the MainDomLock release signal polling task should sleep.
151+
/// </summary>
152+
/// <remarks>
153+
/// Doesn't apply to MainDomSemaphoreLock.
154+
/// <para>
155+
/// The default value is 2000ms.
156+
/// </para>
157+
/// </remarks>
158+
[DefaultValue(StaticMainDomReleaseSignalPollingInterval)]
159+
public int MainDomReleaseSignalPollingInterval { get; set; } = StaticMainDomReleaseSignalPollingInterval;
160+
140161
/// <summary>
141162
/// Gets or sets the telemetry ID.
142163
/// </summary>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace Umbraco.Cms.Core
2+
{
3+
/// <summary>
4+
/// Defines constants.
5+
/// </summary>
6+
public static partial class Constants
7+
{
8+
/// <summary>
9+
/// Defines constants for named http clients.
10+
/// </summary>
11+
public static class HttpClients
12+
{
13+
/// <summary>
14+
/// Name for http client which ignores certificate errors.
15+
/// </summary>
16+
public const string IgnoreCertificateErrors = "Umbraco:HttpClients:IgnoreCertificateErrors";
17+
}
18+
}
19+
}

src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ private void AddCoreServices()
262262
Services.AddSingleton<IValueEditorCache, ValueEditorCache>();
263263

264264
// Register telemetry service used to gather data about installed packages
265+
Services.AddUnique<ISiteIdentifierService, SiteIdentifierService>();
265266
Services.AddUnique<ITelemetryService, TelemetryService>();
266267

267268
// Register a noop IHtmlSanitizer to be replaced

src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public static bool VerifyBackOfficeIdentity(this ClaimsIdentity identity, out Cl
132132
}
133133
}
134134

135-
verifiedIdentity = identity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType ? identity : new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
135+
verifiedIdentity = identity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType ? identity : new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
136136
return true;
137137
}
138138

src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
22
using System.Threading.Tasks;
3+
using Microsoft.Extensions.DependencyInjection;
34
using Microsoft.Extensions.Logging;
45
using Microsoft.Extensions.Options;
56
using Umbraco.Cms.Core.Configuration;
67
using Umbraco.Cms.Core.Configuration.Models;
78
using Umbraco.Cms.Core.Install.Models;
9+
using Umbraco.Cms.Core.Telemetry;
10+
using Umbraco.Cms.Web.Common.DependencyInjection;
811

912
namespace Umbraco.Cms.Core.Install.InstallSteps
1013
{
@@ -13,31 +16,29 @@ namespace Umbraco.Cms.Core.Install.InstallSteps
1316
PerformsAppRestart = false)]
1417
public class TelemetryIdentifierStep : InstallSetupStep<object>
1518
{
16-
private readonly ILogger<TelemetryIdentifierStep> _logger;
1719
private readonly IOptions<GlobalSettings> _globalSettings;
18-
private readonly IConfigManipulator _configManipulator;
20+
private readonly ISiteIdentifierService _siteIdentifierService;
1921

20-
public TelemetryIdentifierStep(ILogger<TelemetryIdentifierStep> logger, IOptions<GlobalSettings> globalSettings, IConfigManipulator configManipulator)
22+
public TelemetryIdentifierStep(
23+
IOptions<GlobalSettings> globalSettings,
24+
ISiteIdentifierService siteIdentifierService)
2125
{
22-
_logger = logger;
2326
_globalSettings = globalSettings;
24-
_configManipulator = configManipulator;
27+
_siteIdentifierService = siteIdentifierService;
2528
}
2629

27-
public override Task<InstallSetupResult> ExecuteAsync(object model)
30+
[Obsolete("Use constructor that takes GlobalSettings and ISiteIdentifierService")]
31+
public TelemetryIdentifierStep(
32+
ILogger<TelemetryIdentifierStep> logger,
33+
IOptions<GlobalSettings> globalSettings,
34+
IConfigManipulator configManipulator)
35+
: this(globalSettings, StaticServiceProvider.Instance.GetRequiredService<ISiteIdentifierService>())
2836
{
29-
// Generate GUID
30-
var telemetrySiteIdentifier = Guid.NewGuid();
31-
32-
try
33-
{
34-
_configManipulator.SetGlobalId(telemetrySiteIdentifier.ToString());
35-
}
36-
catch (Exception ex)
37-
{
38-
_logger.LogError(ex, "Couldn't update config files with a telemetry site identifier");
39-
}
37+
}
4038

39+
public override Task<InstallSetupResult> ExecuteAsync(object model)
40+
{
41+
_siteIdentifierService.TryCreateSiteIdentifier(out _);
4142
return Task.FromResult<InstallSetupResult>(null);
4243
}
4344

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
using System.Runtime.Serialization;
2+
using Umbraco.Cms.Core.Models.Entities;
23

34
namespace Umbraco.Cms.Core.Models.ContentEditing
45
{
56
[DataContract(Name = "historyCleanup", Namespace = "")]
6-
public class HistoryCleanup
7+
public class HistoryCleanup : BeingDirtyBase
78
{
9+
private bool _preventCleanup;
10+
private int? _keepAllVersionsNewerThanDays;
11+
private int? _keepLatestVersionPerDayForDays;
12+
813
[DataMember(Name = "preventCleanup")]
9-
public bool PreventCleanup { get; set; }
14+
public bool PreventCleanup
15+
{
16+
get => _preventCleanup;
17+
set => SetPropertyValueAndDetectChanges(value, ref _preventCleanup, nameof(PreventCleanup));
18+
}
1019

1120
[DataMember(Name = "keepAllVersionsNewerThanDays")]
12-
public int? KeepAllVersionsNewerThanDays { get; set; }
21+
public int? KeepAllVersionsNewerThanDays
22+
{
23+
get => _keepAllVersionsNewerThanDays;
24+
set => SetPropertyValueAndDetectChanges(value, ref _keepAllVersionsNewerThanDays, nameof(KeepAllVersionsNewerThanDays));
25+
}
1326

1427
[DataMember(Name = "keepLatestVersionPerDayForDays")]
15-
public int? KeepLatestVersionPerDayForDays { get; set; }
28+
public int? KeepLatestVersionPerDayForDays
29+
{
30+
get => _keepLatestVersionPerDayForDays;
31+
set => SetPropertyValueAndDetectChanges(value, ref _keepLatestVersionPerDayForDays, nameof(KeepLatestVersionPerDayForDays));
32+
}
1633
}
1734
}

src/Umbraco.Core/Models/ContentType.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,13 @@ public IEnumerable<ITemplate> AllowedTemplates
9696
}
9797
}
9898

99-
public HistoryCleanup HistoryCleanup { get; set; }
99+
private HistoryCleanup _historyCleanup;
100+
101+
public HistoryCleanup HistoryCleanup
102+
{
103+
get => _historyCleanup;
104+
set => SetPropertyValueAndDetectChanges(value, ref _historyCleanup, nameof(HistoryCleanup));
105+
}
100106

101107
/// <summary>
102108
/// Determines if AllowedTemplates contains templateId
@@ -162,5 +168,8 @@ public bool RemoveTemplate(ITemplate template)
162168
/// <inheritdoc />
163169
IContentType IContentType.DeepCloneWithResetIdentities(string newAlias) =>
164170
(IContentType)DeepCloneWithResetIdentities(newAlias);
171+
172+
/// <inheritdoc/>
173+
public override bool IsDirty() => base.IsDirty() || HistoryCleanup.IsDirty();
165174
}
166175
}

src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private void Map(DocumentTypeSave source, IContentType target, MapperContext con
133133

134134
if (target is IContentTypeWithHistoryCleanup targetWithHistoryCleanup)
135135
{
136-
targetWithHistoryCleanup.HistoryCleanup = source.HistoryCleanup;
136+
MapHistoryCleanup(source, targetWithHistoryCleanup);
137137
}
138138

139139
target.AllowedTemplates = source.AllowedTemplates
@@ -147,6 +147,34 @@ private void Map(DocumentTypeSave source, IContentType target, MapperContext con
147147
: _fileService.GetTemplate(source.DefaultTemplate));
148148
}
149149

150+
private static void MapHistoryCleanup(DocumentTypeSave source, IContentTypeWithHistoryCleanup target)
151+
{
152+
// If source history cleanup is null we don't have to map all properties
153+
if (source.HistoryCleanup is null)
154+
{
155+
target.HistoryCleanup = null;
156+
return;
157+
}
158+
159+
// We need to reset the dirty properties, because it is otherwise true, just because the json serializer has set properties
160+
target.HistoryCleanup.ResetDirtyProperties(false);
161+
if (target.HistoryCleanup.PreventCleanup != source.HistoryCleanup.PreventCleanup)
162+
{
163+
target.HistoryCleanup.PreventCleanup = source.HistoryCleanup.PreventCleanup;
164+
}
165+
166+
if (target.HistoryCleanup.KeepAllVersionsNewerThanDays != source.HistoryCleanup.KeepAllVersionsNewerThanDays)
167+
{
168+
target.HistoryCleanup.KeepAllVersionsNewerThanDays = source.HistoryCleanup.KeepAllVersionsNewerThanDays;
169+
}
170+
171+
if (target.HistoryCleanup.KeepLatestVersionPerDayForDays !=
172+
source.HistoryCleanup.KeepLatestVersionPerDayForDays)
173+
{
174+
target.HistoryCleanup.KeepLatestVersionPerDayForDays = source.HistoryCleanup.KeepLatestVersionPerDayForDays;
175+
}
176+
}
177+
150178
// no MapAll - take care
151179
private void Map(MediaTypeSave source, IMediaType target, MapperContext context)
152180
{
@@ -328,7 +356,10 @@ private static void Map(PropertyTypeBasic source, IPropertyType target, MapperCo
328356

329357
if (source.GroupId > 0)
330358
{
331-
target.PropertyGroupId = new Lazy<int>(() => source.GroupId, false);
359+
if (target.PropertyGroupId?.Value != source.GroupId)
360+
{
361+
target.PropertyGroupId = new Lazy<int>(() => source.GroupId, false);
362+
}
332363
}
333364

334365
target.Alias = source.Alias;
@@ -523,7 +554,15 @@ private static void MapSaveToTypeBase<TSource, TSourcePropertyType>(TSource sour
523554
target.Thumbnail = source.Thumbnail;
524555

525556
target.AllowedAsRoot = source.AllowAsRoot;
526-
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
557+
558+
bool allowedContentTypesUnchanged = target.AllowedContentTypes.Select(x => x.Id.Value)
559+
.SequenceEqual(source.AllowedContentTypes);
560+
561+
if (allowedContentTypesUnchanged is false)
562+
{
563+
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
564+
}
565+
527566

528567
if (!(target is IMemberType))
529568
{
@@ -574,13 +613,21 @@ private static void MapSaveToTypeBase<TSource, TSourcePropertyType>(TSource sour
574613

575614
// ensure no duplicate alias, then assign the group properties collection
576615
EnsureUniqueAliases(destProperties);
577-
destGroup.PropertyTypes = new PropertyTypeCollection(isPublishing, destProperties);
616+
if (destGroup.PropertyTypes.SupportsPublishing != isPublishing || destGroup.PropertyTypes.SequenceEqual(destProperties) is false)
617+
{
618+
destGroup.PropertyTypes = new PropertyTypeCollection(isPublishing, destProperties);
619+
}
620+
578621
destGroups.Add(destGroup);
579622
}
580623

581624
// ensure no duplicate name, then assign the groups collection
582625
EnsureUniqueAliases(destGroups);
583-
target.PropertyGroups = new PropertyGroupCollection(destGroups);
626+
627+
if (target.PropertyGroups.SequenceEqual(destGroups) is false)
628+
{
629+
target.PropertyGroups = new PropertyGroupCollection(destGroups);
630+
}
584631

585632
// because the property groups collection was rebuilt, there is no need to remove
586633
// the old groups - they are just gone and will be cleared by the repository

0 commit comments

Comments
 (0)