Merge remote-tracking branch 'origin/v10/dev' into v10/feature/nullable-reference-types-in-Umbraco-Core
# Conflicts: # build/build.ps1 # src/Umbraco.Core/Configuration/ConfigConnectionString.cs # src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs # src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs # src/Umbraco.Core/Models/ContentType.cs # src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs # tests/Umbraco.Tests.AcceptanceTest/package.json
This commit is contained in:
@@ -198,7 +198,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
public bool IsCulturePublished(string culture)
|
||||
// just check _publishInfos
|
||||
// a non-available culture could not become published anyways
|
||||
=> _publishInfos != null && _publishInfos.ContainsKey(culture);
|
||||
=> !culture.IsNullOrWhiteSpace() && _publishInfos != null && _publishInfos.ContainsKey(culture);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsCultureEdited(string culture)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
{
|
||||
Notifications = new List<BackOfficeNotification>();
|
||||
Translations = new List<DictionaryTranslationDisplay>();
|
||||
ContentApps = new List<ContentApp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -37,5 +38,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
/// </summary>
|
||||
[DataMember(Name = "translations")]
|
||||
public List<DictionaryTranslationDisplay> Translations { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Apps for the dictionary item
|
||||
/// </summary>
|
||||
[DataMember(Name = "apps")]
|
||||
public List<ContentApp> ContentApps { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,34 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "historyCleanup", Namespace = "")]
|
||||
public class HistoryCleanup
|
||||
public class HistoryCleanup : BeingDirtyBase
|
||||
{
|
||||
private bool _preventCleanup;
|
||||
private int? _keepAllVersionsNewerThanDays;
|
||||
private int? _keepLatestVersionPerDayForDays;
|
||||
|
||||
[DataMember(Name = "preventCleanup")]
|
||||
public bool PreventCleanup { get; set; }
|
||||
public bool PreventCleanup
|
||||
{
|
||||
get => _preventCleanup;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _preventCleanup, nameof(PreventCleanup));
|
||||
}
|
||||
|
||||
[DataMember(Name = "keepAllVersionsNewerThanDays")]
|
||||
public int? KeepAllVersionsNewerThanDays { get; set; }
|
||||
public int? KeepAllVersionsNewerThanDays
|
||||
{
|
||||
get => _keepAllVersionsNewerThanDays;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _keepAllVersionsNewerThanDays, nameof(KeepAllVersionsNewerThanDays));
|
||||
}
|
||||
|
||||
[DataMember(Name = "keepLatestVersionPerDayForDays")]
|
||||
public int? KeepLatestVersionPerDayForDays { get; set; }
|
||||
public int? KeepLatestVersionPerDayForDays
|
||||
{
|
||||
get => _keepLatestVersionPerDayForDays;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _keepLatestVersionPerDayForDays, nameof(KeepLatestVersionPerDayForDays));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,5 +55,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
/// </summary>
|
||||
[DataMember(Name = "notifications")]
|
||||
public List<BackOfficeNotification> Notifications { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
|
||||
/// </summary>
|
||||
[DataMember(Name = "isDependency", IsRequired = true)]
|
||||
public bool IsDependency { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
/// </summary>
|
||||
[DataMember(Name = "childObjectType", IsRequired = false)]
|
||||
public Guid? ChildObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
|
||||
/// </summary>
|
||||
[DataMember(Name = "isDependency", IsRequired = true)]
|
||||
public bool IsDependency { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// we should not store direct entity
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public ITemplate? DefaultTemplate =>
|
||||
AllowedTemplates?.FirstOrDefault(x => x != null && x.Id == DefaultTemplateId);
|
||||
public ITemplate DefaultTemplate =>
|
||||
AllowedTemplates.FirstOrDefault(x => x != null && x.Id == DefaultTemplateId);
|
||||
|
||||
|
||||
[DataMember]
|
||||
@@ -82,21 +82,27 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// we should not store direct entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public IEnumerable<ITemplate>? AllowedTemplates
|
||||
public IEnumerable<ITemplate> AllowedTemplates
|
||||
{
|
||||
get => _allowedTemplates;
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, nameof(AllowedTemplates), TemplateComparer);
|
||||
|
||||
if (_allowedTemplates?.Any(x => x.Id == _defaultTemplate) == false)
|
||||
if (_allowedTemplates.Any(x => x.Id == _defaultTemplate) == false)
|
||||
{
|
||||
DefaultTemplateId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HistoryCleanup? HistoryCleanup { get; set; }
|
||||
private HistoryCleanup? _historyCleanup;
|
||||
|
||||
public HistoryCleanup? HistoryCleanup
|
||||
{
|
||||
get => _historyCleanup;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _historyCleanup, nameof(HistoryCleanup));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
@@ -162,5 +168,8 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// <inheritdoc />
|
||||
IContentType IContentType.DeepCloneWithResetIdentities(string newAlias) =>
|
||||
(IContentType)DeepCloneWithResetIdentities(newAlias);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsDirty() => base.IsDirty() || HistoryCleanup.IsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,15 @@ using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models
|
||||
{
|
||||
public interface IRelationTypeWithIsDependency : IRelationType
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
bool IsDependency { get; set; }
|
||||
}
|
||||
|
||||
public interface IRelationType : IEntity, IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.ContentApps;
|
||||
@@ -48,6 +48,11 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
}
|
||||
|
||||
public IEnumerable<ContentApp> GetContentApps(IUmbracoEntity source)
|
||||
{
|
||||
return GetContentAppsForEntity(source);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentApp> GetContentAppsForEntity(IEntity source)
|
||||
{
|
||||
var apps = _contentAppDefinitions.GetContentAppsFor(source).ToArray();
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
if (target is IContentTypeWithHistoryCleanup targetWithHistoryCleanup)
|
||||
{
|
||||
targetWithHistoryCleanup.HistoryCleanup = source.HistoryCleanup;
|
||||
MapHistoryCleanup(source, targetWithHistoryCleanup);
|
||||
}
|
||||
|
||||
target.AllowedTemplates = source.AllowedTemplates?
|
||||
@@ -147,6 +147,34 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
: _fileService.GetTemplate(source.DefaultTemplate));
|
||||
}
|
||||
|
||||
private static void MapHistoryCleanup(DocumentTypeSave source, IContentTypeWithHistoryCleanup target)
|
||||
{
|
||||
// If source history cleanup is null we don't have to map all properties
|
||||
if (source.HistoryCleanup is null)
|
||||
{
|
||||
target.HistoryCleanup = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to reset the dirty properties, because it is otherwise true, just because the json serializer has set properties
|
||||
target.HistoryCleanup.ResetDirtyProperties(false);
|
||||
if (target.HistoryCleanup.PreventCleanup != source.HistoryCleanup.PreventCleanup)
|
||||
{
|
||||
target.HistoryCleanup.PreventCleanup = source.HistoryCleanup.PreventCleanup;
|
||||
}
|
||||
|
||||
if (target.HistoryCleanup.KeepAllVersionsNewerThanDays != source.HistoryCleanup.KeepAllVersionsNewerThanDays)
|
||||
{
|
||||
target.HistoryCleanup.KeepAllVersionsNewerThanDays = source.HistoryCleanup.KeepAllVersionsNewerThanDays;
|
||||
}
|
||||
|
||||
if (target.HistoryCleanup.KeepLatestVersionPerDayForDays !=
|
||||
source.HistoryCleanup.KeepLatestVersionPerDayForDays)
|
||||
{
|
||||
target.HistoryCleanup.KeepLatestVersionPerDayForDays = source.HistoryCleanup.KeepLatestVersionPerDayForDays;
|
||||
}
|
||||
}
|
||||
|
||||
// no MapAll - take care
|
||||
private void Map(MediaTypeSave source, IMediaType target, MapperContext context)
|
||||
{
|
||||
@@ -196,7 +224,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
target.AllowCultureVariant = source.VariesByCulture();
|
||||
target.AllowSegmentVariant = source.VariesBySegment();
|
||||
target.ContentApps = _commonMapper.GetContentApps(source);
|
||||
target.ContentApps = _commonMapper.GetContentAppsForEntity(source);
|
||||
|
||||
//sync templates
|
||||
if (source.AllowedTemplates is not null)
|
||||
@@ -331,7 +359,10 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
if (source.GroupId > 0)
|
||||
{
|
||||
target.PropertyGroupId = new Lazy<int>(() => source.GroupId, false);
|
||||
if (target.PropertyGroupId?.Value != source.GroupId)
|
||||
{
|
||||
target.PropertyGroupId = new Lazy<int>(() => source.GroupId, false);
|
||||
}
|
||||
}
|
||||
|
||||
target.Alias = source.Alias;
|
||||
@@ -526,7 +557,15 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.Thumbnail = source.Thumbnail;
|
||||
|
||||
target.AllowedAsRoot = source.AllowAsRoot;
|
||||
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
|
||||
|
||||
bool allowedContentTypesUnchanged = target.AllowedContentTypes.Select(x => x.Id.Value)
|
||||
.SequenceEqual(source.AllowedContentTypes);
|
||||
|
||||
if (allowedContentTypesUnchanged is false)
|
||||
{
|
||||
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
|
||||
}
|
||||
|
||||
|
||||
if (!(target is IMemberType))
|
||||
{
|
||||
@@ -577,13 +616,21 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
// ensure no duplicate alias, then assign the group properties collection
|
||||
EnsureUniqueAliases(destProperties);
|
||||
destGroup.PropertyTypes = new PropertyTypeCollection(isPublishing, destProperties);
|
||||
if (destGroup.PropertyTypes.SupportsPublishing != isPublishing || destGroup.PropertyTypes.SequenceEqual(destProperties) is false)
|
||||
{
|
||||
destGroup.PropertyTypes = new PropertyTypeCollection(isPublishing, destProperties);
|
||||
}
|
||||
|
||||
destGroups.Add(destGroup);
|
||||
}
|
||||
|
||||
// ensure no duplicate name, then assign the groups collection
|
||||
EnsureUniqueAliases(destGroups);
|
||||
target.PropertyGroups = new PropertyGroupCollection(destGroups);
|
||||
|
||||
if (target.PropertyGroups.SequenceEqual(destGroups) is false)
|
||||
{
|
||||
target.PropertyGroups = new PropertyGroupCollection(destGroups);
|
||||
}
|
||||
|
||||
// because the property groups collection was rebuilt, there is no need to remove
|
||||
// the old groups - they are just gone and will be cleared by the repository
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
@@ -14,12 +15,20 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
public class DictionaryMapDefinition : IMapDefinition
|
||||
{
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly CommonMapper _commonMapper;
|
||||
|
||||
[Obsolete("Use the constructor with the CommonMapper")]
|
||||
public DictionaryMapDefinition(ILocalizationService localizationService)
|
||||
{
|
||||
_localizationService = localizationService;
|
||||
}
|
||||
|
||||
public DictionaryMapDefinition(ILocalizationService localizationService, CommonMapper commonMapper)
|
||||
{
|
||||
_localizationService = localizationService;
|
||||
_commonMapper = commonMapper;
|
||||
}
|
||||
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<IDictionaryItem, EntityBasic>((source, context) => new EntityBasic(), Map);
|
||||
@@ -44,6 +53,10 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.Name = source.ItemKey;
|
||||
target.ParentId = source.ParentId ?? Guid.Empty;
|
||||
target.Udi = Udi.Create(Constants.UdiEntityType.DictionaryItem, source.Key);
|
||||
if (_commonMapper != null)
|
||||
{
|
||||
target.ContentApps.AddRange(_commonMapper.GetContentAppsForEntity(source));
|
||||
}
|
||||
|
||||
// build up the path to make it possible to set active item in tree
|
||||
// TODO: check if there is a better way
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.ChildObjectType = source.ChildObjectType;
|
||||
target.Id = source.Id;
|
||||
target.IsBidirectional = source.IsBidirectional;
|
||||
|
||||
if (source is IRelationTypeWithIsDependency sourceWithIsDependency)
|
||||
{
|
||||
target.IsDependency = sourceWithIsDependency.IsDependency;
|
||||
}
|
||||
target.Key = source.Key;
|
||||
target.Name = source.Name;
|
||||
target.Alias = source.Alias;
|
||||
@@ -74,6 +79,11 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.ChildObjectType = source.ChildObjectType;
|
||||
target.Id = source.Id.TryConvertTo<int>().Result;
|
||||
target.IsBidirectional = source.IsBidirectional;
|
||||
if (target is IRelationTypeWithIsDependency targetWithIsDependency)
|
||||
{
|
||||
targetWithIsDependency.IsDependency = source.IsDependency;
|
||||
}
|
||||
|
||||
target.Key = source.Key;
|
||||
target.Name = source.Name;
|
||||
target.ParentObjectType = source.ParentObjectType;
|
||||
|
||||
44
src/Umbraco.Core/Models/RelationItem.cs
Normal file
44
src/Umbraco.Core/Models/RelationItem.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models
|
||||
{
|
||||
[DataContract(Name = "relationItem", Namespace = "")]
|
||||
public class RelationItem
|
||||
{
|
||||
[DataMember(Name = "id")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[DataMember(Name = "key")]
|
||||
public Guid NodeKey { get; set; }
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
public string NodeName { get; set; }
|
||||
|
||||
[DataMember(Name = "type")]
|
||||
public string NodeType { get; set; }
|
||||
|
||||
[DataMember(Name = "udi")]
|
||||
public Udi NodeUdi => Udi.Create(NodeType, NodeKey);
|
||||
|
||||
[DataMember(Name = "icon")]
|
||||
public string ContentTypeIcon { get; set; }
|
||||
|
||||
[DataMember(Name = "alias")]
|
||||
public string ContentTypeAlias { get; set; }
|
||||
|
||||
[DataMember(Name = "contentTypeName")]
|
||||
public string ContentTypeName { get; set; }
|
||||
|
||||
[DataMember(Name = "relationTypeName")]
|
||||
public string RelationTypeName { get; set; }
|
||||
|
||||
[DataMember(Name = "relationTypeIsBidirectional")]
|
||||
public bool RelationTypeIsBidirectional { get; set; }
|
||||
|
||||
[DataMember(Name = "relationTypeIsDependency")]
|
||||
public bool RelationTypeIsDependency { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,28 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class RelationType : EntityBase, IRelationType
|
||||
public class RelationType : EntityBase, IRelationType, IRelationTypeWithIsDependency
|
||||
{
|
||||
private string _name;
|
||||
private string _alias;
|
||||
private bool _isBidirectional;
|
||||
private bool _isDependency;
|
||||
private Guid? _parentObjectType;
|
||||
private Guid? _childObjectType;
|
||||
|
||||
public RelationType(string alias, string name)
|
||||
: this(name: name, alias: alias, false, null, null)
|
||||
: this(name: name, alias: alias, false, null, null, false)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use ctor with isDependency parameter")]
|
||||
public RelationType(string name, string alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType)
|
||||
:this(name,alias,isBidrectional, parentObjectType, childObjectType, false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public RelationType(string name, string alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType, bool isDependency)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
|
||||
@@ -32,6 +40,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
_name = name;
|
||||
_alias = alias;
|
||||
_isBidirectional = isBidrectional;
|
||||
_isDependency = isDependency;
|
||||
_parentObjectType = parentObjectType;
|
||||
_childObjectType = childObjectType;
|
||||
}
|
||||
@@ -88,5 +97,11 @@ namespace Umbraco.Cms.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _childObjectType, nameof(ChildObjectType));
|
||||
}
|
||||
|
||||
|
||||
public bool IsDependency
|
||||
{
|
||||
get => _isDependency;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _isDependency, nameof(IsDependency));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user