Merge remote-tracking branch 'origin/v12/dev' into v13/dev

This commit is contained in:
Bjarke Berg
2023-11-14 09:31:04 +01:00
30 changed files with 370 additions and 101 deletions

7
global.json Normal file
View File

@@ -0,0 +1,7 @@
{
"sdk": {
"version": "7.0.400",
"rollForward": "latestFeature",
"allowPrerelease": false
}
}

View File

@@ -6,6 +6,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.13" />
</ItemGroup>
<ItemGroup>

View File

@@ -6,6 +6,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
</ItemGroup>
<ItemGroup>

View File

@@ -9,6 +9,9 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-rc.2.*"/>
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.9.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.13" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.5.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -6,6 +6,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.13" />
</ItemGroup>
<ItemGroup>

View File

@@ -9,15 +9,22 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// </summary>
public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory
{
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures)
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
{
yield return new KeyValuePair<string, IEnumerable<object?>>(
property.Alias,
property.GetValue(culture, segment, published).Yield());
}
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
/// <inheritdoc />
[Obsolete("Use the non-obsolete overload, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture,
string? segment, bool published, IEnumerable<string> availableCultures)
=> GetIndexValues(property, culture, segment, published, availableCultures,
new Dictionary<Guid, IContentType>());
[Obsolete("Use the non-obsolete overload, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>());
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>(), new Dictionary<Guid, IContentType>());
}

View File

@@ -22,9 +22,14 @@ public interface IPropertyIndexValueFactory
/// more than one value for a given field.
/// </para>
/// </remarks>
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture,
string? segment, bool published, IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary) => GetIndexValues(property, culture, segment, published);
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures)
=> GetIndexValues(property, culture, segment, published);
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published);
}

View File

@@ -3,6 +3,7 @@ using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
@@ -39,13 +40,13 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
}
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures)
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
{
var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
@@ -63,7 +64,7 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
return result;
}
result.AddRange(Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures));
result.AddRange(Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures, contentTypeDictionary));
}
catch (InvalidCastException)
{
@@ -87,9 +88,31 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
return summary;
}
/// <inheritdoc />
[Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 14.")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures)
=> GetIndexValues(
property,
culture,
segment,
published,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
[Obsolete("Use method overload that has availableCultures, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>());
=> GetIndexValues(
property,
culture,
segment,
published,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
/// <summary>
/// Method to return a list of summary of the content. By default this returns an empty list
@@ -104,7 +127,7 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
/// <summary>
/// Method that handle the deserialized object.
/// </summary>
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
[Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")]
protected abstract IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
@@ -112,6 +135,15 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
string? segment,
bool published);
[Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")]
protected virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures) => Handle(deserializedPropertyValue, property, culture, segment, published);
/// <summary>
/// Method that handle the deserialized object.
/// </summary>
@@ -121,6 +153,7 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures) =>
Handle(deserializedPropertyValue, property, culture, segment, published);
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
=> Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures);
}

View File

@@ -8,6 +8,12 @@ namespace Umbraco.Cms.Core.PropertyEditors;
public class NoopPropertyIndexValueFactory : IPropertyIndexValueFactory
{
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
=> Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures) => Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]

View File

@@ -3575,6 +3575,7 @@ public class ContentService : RepositoryService, IContentService
Audit(AuditType.Save, userId, content.Id, $"Saved content template: {content.Name}");
scope.Notifications.Publish(new ContentSavedBlueprintNotification(content, evtMsgs));
scope.Notifications.Publish(new ContentTreeChangeNotification(content, TreeChangeTypes.RefreshNode, evtMsgs));
scope.Complete();
}
@@ -3589,6 +3590,7 @@ public class ContentService : RepositoryService, IContentService
scope.WriteLock(Constants.Locks.ContentTree);
_documentBlueprintRepository.Delete(content);
scope.Notifications.Publish(new ContentDeletedBlueprintNotification(content, evtMsgs));
scope.Notifications.Publish(new ContentTreeChangeNotification(content, TreeChangeTypes.Remove, evtMsgs));
scope.Complete();
}
}
@@ -3689,6 +3691,7 @@ public class ContentService : RepositoryService, IContentService
}
scope.Notifications.Publish(new ContentDeletedBlueprintNotification(blueprints, evtMsgs));
scope.Notifications.Publish(new ContentTreeChangeNotification(blueprints, TreeChangeTypes.Remove, evtMsgs));
scope.Complete();
}
}

View File

@@ -17,6 +17,25 @@
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="8.0.0-rc.2.*" />
<PackageReference Include="System.Runtime.Caching" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.13" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.13" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="7.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageReference Include="System.Runtime.Caching" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<!-- Update implicit dependencies to fix security issues, even though we do not use them explicitly and they are taken from the shared framework instead of NuGet -->
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="7.0.1" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,6 +1,9 @@
using Examine;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.Examine;
@@ -24,9 +27,26 @@ public abstract class BaseValueSetBuilder<TContent> : IValueSetBuilder<TContent>
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary<string, IEnumerable<object?>>? values)
=> AddPropertyValue(property, culture, segment, values, Enumerable.Empty<string>());
=> AddPropertyValue(
property,
culture,
segment,
values,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary<string, IEnumerable<object?>>? values, IEnumerable<string> availableCultures)
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
protected void AddPropertyValue(IProperty property, string? culture, string? segment,
IDictionary<string, IEnumerable<object?>>? values, IEnumerable<string> availableCultures)
=> AddPropertyValue(
property,
culture,
segment,
values,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary<string, IEnumerable<object?>>? values, IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
{
IDataEditor? editor = _propertyEditors[property.PropertyType.PropertyEditorAlias];
if (editor == null)
@@ -35,7 +55,7 @@ public abstract class BaseValueSetBuilder<TContent> : IValueSetBuilder<TContent>
}
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> indexVals =
editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures);
editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures, contentTypeDictionary);
foreach (KeyValuePair<string, IEnumerable<object?>> keyVal in indexVals)
{
if (keyVal.Key.IsNullOrWhiteSpace())

View File

@@ -21,13 +21,34 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
private static readonly object[] NoValue = new[] { "n" };
private static readonly object[] YesValue = new[] { "y" };
private readonly IScopeProvider _scopeProvider;
private readonly ICoreScopeProvider _scopeProvider;
private readonly IShortStringHelper _shortStringHelper;
private readonly UrlSegmentProviderCollection _urlSegmentProviders;
private readonly IUserService _userService;
private readonly ILocalizationService _localizationService;
private readonly IContentTypeService _contentTypeService;
public ContentValueSetBuilder(
PropertyEditorCollection propertyEditors,
UrlSegmentProviderCollection urlSegmentProviders,
IUserService userService,
IShortStringHelper shortStringHelper,
ICoreScopeProvider scopeProvider,
bool publishedValuesOnly,
ILocalizationService localizationService,
IContentTypeService contentTypeService)
: base(propertyEditors, publishedValuesOnly)
{
_urlSegmentProviders = urlSegmentProviders;
_userService = userService;
_shortStringHelper = shortStringHelper;
_scopeProvider = scopeProvider;
_localizationService = localizationService;
_contentTypeService = contentTypeService;
}
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
public ContentValueSetBuilder(
PropertyEditorCollection propertyEditors,
UrlSegmentProviderCollection urlSegmentProviders,
@@ -36,16 +57,20 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
IScopeProvider scopeProvider,
bool publishedValuesOnly,
ILocalizationService localizationService)
: base(propertyEditors, publishedValuesOnly)
: this(
propertyEditors,
urlSegmentProviders,
userService,
shortStringHelper,
scopeProvider,
publishedValuesOnly,
localizationService,
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
{
_urlSegmentProviders = urlSegmentProviders;
_userService = userService;
_shortStringHelper = shortStringHelper;
_scopeProvider = scopeProvider;
_localizationService = localizationService;
}
[Obsolete("Use the constructor that takes an ILocalizationService, scheduled for removal in v14")]
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
public ContentValueSetBuilder(
PropertyEditorCollection propertyEditors,
UrlSegmentProviderCollection urlSegmentProviders,
@@ -60,7 +85,8 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
shortStringHelper,
scopeProvider,
publishedValuesOnly,
StaticServiceProvider.Instance.GetRequiredService<ILocalizationService>())
StaticServiceProvider.Instance.GetRequiredService<ILocalizationService>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
{
}
@@ -72,7 +98,7 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
// We can lookup all of the creator/writer names at once which can save some
// processing below instead of one by one.
using (IScope scope = _scopeProvider.CreateScope())
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
creatorIds = _userService.GetProfilesById(content.Select(x => x.CreatorId).ToArray())
.ToDictionary(x => x.Id, x => x);
@@ -86,6 +112,8 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
private IEnumerable<ValueSet> GetValueSetsEnumerable(IContent[] content, Dictionary<int, IProfile> creatorIds, Dictionary<int, IProfile> writerIds)
{
IDictionary<Guid, IContentType> contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key);
// TODO: There is a lot of boxing going on here and ultimately all values will be boxed by Lucene anyways
// but I wonder if there's a way to reduce the boxing that we have to do or if it will matter in the end since
// Lucene will do it no matter what? One idea was to create a `FieldValue` struct which would contain `object`, `object[]`, `ValueType` and `ValueType[]`
@@ -162,13 +190,13 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
{
if (!property.PropertyType.VariesByCulture())
{
AddPropertyValue(property, null, null, values, availableCultures);
AddPropertyValue(property, null, null, values, availableCultures, contentTypeDictionary);
}
else
{
foreach (var culture in c.AvailableCultures)
{
AddPropertyValue(property, culture.ToLowerInvariant(), null, values, availableCultures);
AddPropertyValue(property, culture.ToLowerInvariant(), null, values, availableCultures, contentTypeDictionary);
}
}
}

View File

@@ -1,10 +1,12 @@
using Examine;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.Examine;
@@ -14,6 +16,7 @@ public class MediaValueSetBuilder : BaseValueSetBuilder<IMedia>
private readonly ContentSettings _contentSettings;
private readonly MediaUrlGeneratorCollection _mediaUrlGenerators;
private readonly IShortStringHelper _shortStringHelper;
private readonly IContentTypeService _contentTypeService;
private readonly UrlSegmentProviderCollection _urlSegmentProviders;
private readonly IUserService _userService;
@@ -23,19 +26,41 @@ public class MediaValueSetBuilder : BaseValueSetBuilder<IMedia>
MediaUrlGeneratorCollection mediaUrlGenerators,
IUserService userService,
IShortStringHelper shortStringHelper,
IOptions<ContentSettings> contentSettings)
IOptions<ContentSettings> contentSettings,
IContentTypeService contentTypeService)
: base(propertyEditors, false)
{
_urlSegmentProviders = urlSegmentProviders;
_mediaUrlGenerators = mediaUrlGenerators;
_userService = userService;
_shortStringHelper = shortStringHelper;
_contentTypeService = contentTypeService;
_contentSettings = contentSettings.Value;
}
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
public MediaValueSetBuilder(
PropertyEditorCollection propertyEditors,
UrlSegmentProviderCollection urlSegmentProviders,
MediaUrlGeneratorCollection mediaUrlGenerators,
IUserService userService,
IShortStringHelper shortStringHelper,
IOptions<ContentSettings> contentSettings)
: this(propertyEditors,
urlSegmentProviders,
mediaUrlGenerators,
userService,
shortStringHelper,
contentSettings,
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
{
}
/// <inheritdoc />
public override IEnumerable<ValueSet> GetValueSets(params IMedia[] media)
{
IDictionary<Guid, IContentType> contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key);
foreach (IMedia m in media)
{
var urlValue = m.GetUrlSegment(_shortStringHelper, _urlSegmentProviders);
@@ -65,7 +90,7 @@ public class MediaValueSetBuilder : BaseValueSetBuilder<IMedia>
foreach (IProperty property in m.Properties)
{
AddPropertyValue(property, null, null, values, m.AvailableCultures);
AddPropertyValue(property, null, null, values, m.AvailableCultures, contentTypeDictionary);
}
var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Media, m.ContentType.Alias, values);

View File

@@ -1,20 +1,34 @@
using Examine;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.Examine;
public class MemberValueSetBuilder : BaseValueSetBuilder<IMember>
{
public MemberValueSetBuilder(PropertyEditorCollection propertyEditors)
private readonly IContentTypeService _contentTypeService;
public MemberValueSetBuilder(PropertyEditorCollection propertyEditors, IContentTypeService contentTypeService)
: base(propertyEditors, false)
{
_contentTypeService = contentTypeService;
}
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
public MemberValueSetBuilder(PropertyEditorCollection propertyEditors)
: this(propertyEditors, StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
{
}
/// <inheritdoc />
public override IEnumerable<ValueSet> GetValueSets(params IMember[] members)
{
IDictionary<Guid, IContentType> contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key);
foreach (IMember m in members)
{
var values = new Dictionary<string, IEnumerable<object?>>
@@ -37,7 +51,7 @@ public class MemberValueSetBuilder : BaseValueSetBuilder<IMember>
foreach (IProperty property in m.Properties)
{
AddPropertyValue(property, null, null, values, m.AvailableCultures);
AddPropertyValue(property, null, null, values, m.AvailableCultures, contentTypeDictionary);
}
var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Member, m.ContentType.Alias, values);

View File

@@ -67,7 +67,7 @@ public class ThreadAbortExceptionEnricher : ILogEventEnricher
private void DumpThreadAborts(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (!IsTimeoutThreadAbortException(logEvent.Exception))
if (logEvent.Exception is null || !IsTimeoutThreadAbortException(logEvent.Exception))
{
return;
}

View File

@@ -38,10 +38,13 @@ internal sealed class BlockValuePropertyIndexValueFactory :
_contentTypeService = contentTypeService;
}
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
protected override IContentType? GetContentTypeOfNestedItem(BlockItemData input) =>
_contentTypeService.Get(input.ContentTypeKey);
protected override IContentType? GetContentTypeOfNestedItem(BlockItemData input, IDictionary<Guid, IContentType> contentTypeDictionary)
=> contentTypeDictionary.TryGetValue(input.ContentTypeKey, out var result) ? result : null;
protected override IDictionary<string, object?> GetRawProperty(BlockItemData blockItemData) =>
blockItemData.RawPropertyValues;

View File

@@ -2,19 +2,20 @@
// See LICENSE for more details.
using System.Runtime.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.Editors;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Extensions;
using Umbraco.Cms.Web.Common.DependencyInjection;
namespace Umbraco.Cms.Core.PropertyEditors;
@@ -26,11 +27,57 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
NullValueHandling = NullValueHandling.Ignore,
};
private readonly IEntityService _entityService;
private readonly ILogger<MultiUrlPickerValueEditor> _logger;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly IPublishedUrlProvider _publishedUrlProvider;
private readonly IContentService _contentService;
private readonly IMediaService _mediaService;
public MultiUrlPickerValueEditor(
ILogger<MultiUrlPickerValueEditor> logger,
ILocalizedTextService localizedTextService,
IShortStringHelper shortStringHelper,
DataEditorAttribute attribute,
IPublishedUrlProvider publishedUrlProvider,
IJsonSerializer jsonSerializer,
IIOHelper ioHelper,
IContentService contentService,
IMediaService mediaService)
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_publishedUrlProvider = publishedUrlProvider;
_contentService = contentService;
_mediaService = mediaService;
}
[Obsolete("Use non-obsolete constructor. Scheduled for removal in Umbraco 14.")]
public MultiUrlPickerValueEditor(
IEntityService entityService,
IPublishedSnapshotAccessor publishedSnapshotAccessor,
ILogger<MultiUrlPickerValueEditor> logger,
ILocalizedTextService localizedTextService,
IShortStringHelper shortStringHelper,
DataEditorAttribute attribute,
IPublishedUrlProvider publishedUrlProvider,
IJsonSerializer jsonSerializer,
IIOHelper ioHelper,
IContentService contentService,
IMediaService mediaService)
:this(
logger,
localizedTextService,
shortStringHelper,
attribute,
publishedUrlProvider,
jsonSerializer,
ioHelper,
contentService,
mediaService)
{
}
[Obsolete("Use non-obsolete constructor. Scheduled for removal in Umbraco 14.")]
public MultiUrlPickerValueEditor(
IEntityService entityService,
IPublishedSnapshotAccessor publishedSnapshotAccessor,
@@ -41,13 +88,18 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
IPublishedUrlProvider publishedUrlProvider,
IJsonSerializer jsonSerializer,
IIOHelper ioHelper)
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
: this(
logger,
localizedTextService,
shortStringHelper,
attribute,
publishedUrlProvider,
jsonSerializer,
ioHelper,
StaticServiceProvider.Instance.GetRequiredService<IContentService>(),
StaticServiceProvider.Instance.GetRequiredService<IMediaService>())
{
_entityService = entityService ?? throw new ArgumentNullException(nameof(entityService));
_publishedSnapshotAccessor = publishedSnapshotAccessor ??
throw new ArgumentNullException(nameof(publishedSnapshotAccessor));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_publishedUrlProvider = publishedUrlProvider;
}
public IEnumerable<UmbracoEntityReference> GetReferences(object? value)
@@ -86,26 +138,6 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
{
List<LinkDto>? links = JsonConvert.DeserializeObject<List<LinkDto>>(value);
List<LinkDto>? documentLinks = links?.FindAll(link =>
link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Document);
List<LinkDto>? mediaLinks = links?.FindAll(link =>
link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Media);
var entities = new List<IEntitySlim>();
if (documentLinks?.Count > 0)
{
entities.AddRange(
_entityService.GetAll(
UmbracoObjectTypes.Document,
documentLinks.Select(link => link.Udi!.Guid).ToArray()));
}
if (mediaLinks?.Count > 0)
{
entities.AddRange(
_entityService.GetAll(UmbracoObjectTypes.Media, mediaLinks.Select(link => link.Udi!.Guid).ToArray()));
}
var result = new List<LinkDisplay>();
if (links is null)
{
@@ -114,7 +146,7 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
foreach (LinkDto dto in links)
{
GuidUdi? udi = null;
GuidUdi? udi = dto.Udi;
var icon = "icon-link";
var published = true;
var trashed = false;
@@ -122,35 +154,30 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
if (dto.Udi != null)
{
IUmbracoEntity? entity = entities.Find(e => e.Key == dto.Udi.Guid);
if (entity == null)
if (dto.Udi.EntityType == Constants.UdiEntityType.Document)
{
continue;
}
url = _publishedUrlProvider.GetUrl(dto.Udi.Guid, UrlMode.Relative, culture);
IContent? c = _contentService.GetById(dto.Udi.Guid);
IPublishedSnapshot publishedSnapshot = _publishedSnapshotAccessor.GetRequiredPublishedSnapshot();
if (entity is IDocumentEntitySlim documentEntity)
{
icon = documentEntity.ContentTypeIcon;
published = culture == null
? documentEntity.Published
: documentEntity.PublishedCultures.Contains(culture);
udi = new GuidUdi(Constants.UdiEntityType.Document, documentEntity.Key);
url = publishedSnapshot.Content?.GetById(entity.Key)?.Url(_publishedUrlProvider) ?? "#";
trashed = documentEntity.Trashed;
if (c is not null)
{
published = culture == null
? c.Published
: c.PublishedCultures.Contains(culture);
icon = c.ContentType.Icon;
trashed = c.Trashed;
}
}
else if (entity is IContentEntitySlim contentEntity)
else if (dto.Udi.EntityType == Constants.UdiEntityType.Media)
{
icon = contentEntity.ContentTypeIcon;
published = !contentEntity.Trashed;
udi = new GuidUdi(Constants.UdiEntityType.Media, contentEntity.Key);
url = publishedSnapshot.Media?.GetById(entity.Key)?.Url(_publishedUrlProvider) ?? "#";
trashed = contentEntity.Trashed;
}
else
{
// Not supported
continue;
url = _publishedUrlProvider.GetMediaUrl(dto.Udi.Guid, UrlMode.Relative, culture);
IMedia? m = _mediaService.GetById(dto.Udi.Guid);
if (m is not null)
{
published = m.Trashed is false;
icon = m.ContentType.Icon;
trashed = m.Trashed;
}
}
}

View File

@@ -39,6 +39,11 @@ internal sealed class NestedContentPropertyIndexValueFactory
_contentTypeService = contentTypeService;
}
protected override IContentType? GetContentTypeOfNestedItem(
NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue input, IDictionary<Guid, IContentType> contentTypeDictionary)
=> contentTypeDictionary.Values.FirstOrDefault(x=>x.Alias.Equals(input.ContentTypeAlias));
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
protected override IContentType? GetContentTypeOfNestedItem(
NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue input)
=> _contentTypeService.Get(input.ContentTypeAlias);

View File

@@ -4,6 +4,7 @@ using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Examine;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
@@ -42,20 +43,39 @@ internal abstract class NestedPropertyIndexValueFactoryBase<TSerialized, TItem>
bool published) =>
Handle(deserializedPropertyValue, property, culture, segment, published, Enumerable.Empty<string>());
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures)
IEnumerable<string> availableCultures) =>
Handle(
deserializedPropertyValue,
property,
culture,
segment,
published,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
{
var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
var index = 0;
foreach (TItem nestedContentRowValue in GetDataItems(deserializedPropertyValue))
{
IContentType? contentType = GetContentTypeOfNestedItem(nestedContentRowValue);
IContentType? contentType = GetContentTypeOfNestedItem(nestedContentRowValue, contentTypeDictionary);
if (contentType is null)
{
@@ -125,6 +145,9 @@ internal abstract class NestedPropertyIndexValueFactoryBase<TSerialized, TItem>
/// <summary>
/// Gets the content type using the nested item.
/// </summary>
protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem, IDictionary<Guid, IContentType> contentTypeDictionary);
[Obsolete("Use non-obsolete overload. Scheduled for removal in Umbraco 14.")]
protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem);
/// <summary>

View File

@@ -27,6 +27,23 @@
<PackageReference Include="NPoco" Version="5.7.1" />
<PackageReference Include="Serilog" Version="3.0.1" />
<PackageReference Include="OpenIddict.Abstractions" Version="4.9.0" />
<PackageReference Include="MailKit" Version="4.1.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
<PackageReference Include="IPNetwork2" Version="2.6.618" />
<PackageReference Include="Markdown" Version="2.2.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="MiniProfiler.Shared" Version="4.3.8" />
<PackageReference Include="NPoco" Version="5.7.1" />
<PackageReference Include="OpenIddict.Abstractions" Version="4.5.0" />
<PackageReference Include="Serilog" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.13" />
<PackageReference Include="ncrontab" Version="3.3.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NPoco.SqlServer" Version="5.7.1" />
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.2" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
@@ -37,6 +54,9 @@
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Map" Version="1.0.2" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="7.0.3" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="7.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -224,7 +224,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Document);
foreach (ContentSourceDto row in dtos)
{
@@ -242,7 +242,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Document);
foreach (ContentSourceDto row in dtos)
{
@@ -265,7 +265,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Document);
foreach (ContentSourceDto row in dtos)
{
@@ -301,7 +301,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Media);
foreach (ContentSourceDto row in dtos)
{
@@ -319,7 +319,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Media);
foreach (ContentSourceDto row in dtos)
{
@@ -342,7 +342,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Media);
foreach (ContentSourceDto row in dtos)
{
@@ -990,7 +990,7 @@ WHERE cmsContentNu.nodeId IN (
return s;
}
private IEnumerable<ContentSourceDto> GetContentNodeDtos(Sql<ISqlContext> sql)
private IEnumerable<ContentSourceDto> GetContentNodeDtos(Sql<ISqlContext> sql, Guid nodeObjectType)
{
// We need to page here. We don't want to iterate over every single row in one connection cuz this can cause an SQL Timeout.
// We also want to read with a db reader and not load everything into memory, QueryPaged lets us do that.
@@ -1000,7 +1000,7 @@ WHERE cmsContentNu.nodeId IN (
{
// Use a more efficient COUNT query
Sql<ISqlContext>? sqlCountQuery = SqlContentSourcesCount()
.Append(SqlObjectTypeNotTrashed(SqlContext, Constants.ObjectTypes.Document));
.Append(SqlObjectTypeNotTrashed(SqlContext, nodeObjectType));
Sql<ISqlContext>? sqlCount =
SqlContext.Sql("SELECT COUNT(*) FROM (").Append(sqlCountQuery).Append(") npoco_tbl");

View File

@@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="MessagePack" Version="2.5.124" />
<PackageReference Include="MessagePack" Version="2.5.129" />
<PackageReference Include="Umbraco.CSharpTest.Net.Collections" Version="15.0.0" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

View File

@@ -12,7 +12,11 @@
<PackageReference Include="Dazinator.Extensions.FileProviders" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.13" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.13" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.3.8" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="SixLabors.ImageSharp.Web" Version="2.0.2" />
<PackageReference Include="Smidge.InMemory" Version="4.3.0" />
<PackageReference Include="Smidge.Nuglify" Version="4.3.0" />
</ItemGroup>

View File

@@ -3,7 +3,7 @@
<p>
In order to run Umbraco, you'll need to update your permission settings.
Detailed information about the correct file and folder permissions for Umbraco can be found
<a href="https://docs.umbraco.com/umbraco-cms/fundamentals/setup/server-setup/permissions"><strong>here</strong></a>.
<a href="https://docs.umbraco.com/umbraco-cms/v/10.latest-lts/fundamentals/setup/server-setup/permissions"><strong>here</strong></a>.
</p>
<p>
The following report list the permissions that are currently failing. Once the permissions are fixed press the 'Go back' button to restart the installation.

View File

@@ -17,6 +17,14 @@
<!-- Opt-in to app-local ICU to ensure consistent globalization APIs across different platforms -->
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="72.1.0.3" />
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="72.1.0.3" Condition="$(RuntimeIdentifier.StartsWith('linux')) or $(RuntimeIdentifier.StartsWith('win')) or ('$(RuntimeIdentifier)' == '' and !$([MSBuild]::IsOSPlatform('osx')))" />
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2.0.9" Condition="$(RuntimeIdentifier.StartsWith('linux')) or $(RuntimeIdentifier.StartsWith('win')) or ('$(RuntimeIdentifier)' == '' and !$([MSBuild]::IsOSPlatform('osx')))" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.13">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>

View File

@@ -13,7 +13,7 @@
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.3.8" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="AutoFixture.NUnit3" Version="4.18.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit" Version="3.14.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -13,6 +13,8 @@
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.0-rc.2.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.13" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" PrivateAssets="all" />
</ItemGroup>

View File

@@ -7,6 +7,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="AngleSharp" Version="1.0.4" />
<PackageReference Include="AngleSharp" Version="1.0.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="System.Data.Odbc" Version="8.0.0-rc.2.*" />
<PackageReference Include="System.Data.OleDb" Version="8.0.0-rc.2.*" />

View File

@@ -132,6 +132,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
LICENSE.md = LICENSE.md
umbraco.sln.DotSettings = umbraco.sln.DotSettings
version.json = version.json
global.json = global.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{20CE9C97-9314-4A19-BCF1-D12CF49B7205}"