V14: Remove old backoffice project. (#15752)
* Move magical route to management api * Move auth around * Remove "New" cookies, as they are no longer needed * Move all installer related * Remove BackOfficeServerVariables.cs and trees * Move webhooks to management api * Remove remainting controllers * Remove last services * Move preview to management api * Remove mroe extensions * Remove tours * Remove old Auth handlers * Remove server variables entirely * Remove old backoffice controller * Remove controllers namespace entirely * Move rest of preview * move last services * Move language file extension * Remove old backoffice entirely (Backoffice and Web.UI projects) * Clean up unused security classes * Fix up installer route * Remove obsolete tests * Fix up DI in integration test * Add missing property mapping * Move core mapping into core * Add composers to integration test * remove identity * Fix up DI * Outcomment failing test :) * Fix up remaining test * Update mapper * Remove the actual project files * Remove backoffice cs proj * Remove old backoffice from yml * Run belissima before login * Remove caching * Refactor file paths * Remove belle from static assets * Dont refer to old project in templates * update gitignore * Add missing files * Remove install view as its no longer used * Fix up failing test * Remove outcommented code * Update submodule to latest * fix build --------- Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
@@ -152,9 +152,9 @@ public class ContentSettings
|
||||
internal const string StaticMacroErrors = "Inline";
|
||||
internal const string StaticDisallowedUploadFiles = "ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,xamlx";
|
||||
internal const bool StaticShowDeprecatedPropertyEditors = false;
|
||||
internal const string StaticLoginBackgroundImage = "assets/img/login.jpg";
|
||||
internal const string StaticLoginLogoImage = "assets/img/application/umbraco_logo_blue.svg";
|
||||
internal const string StaticLoginLogoImageAlternative = "assets/img/application/umbraco_logo_blue.svg";
|
||||
internal const string StaticLoginBackgroundImage = "login/login.jpg";
|
||||
internal const string StaticLoginLogoImage = "login/logo_dark.svg";
|
||||
internal const string StaticLoginLogoImageAlternative = "login/logo_light.svg";
|
||||
internal const bool StaticHideBackOfficeLogo = false;
|
||||
internal const bool StaticDisableDeleteWhenReferenced = false;
|
||||
internal const bool StaticDisableUnpublishWhenReferenced = false;
|
||||
|
||||
@@ -77,11 +77,6 @@ public static partial class Constants
|
||||
public const string BackOfficeTokenAuthenticationType = "UmbracoBackOfficeToken";
|
||||
public const string BackOfficeTwoFactorAuthenticationType = "UmbracoTwoFactorCookie";
|
||||
public const string BackOfficeTwoFactorRememberMeAuthenticationType = "UmbracoTwoFactorRememberMeCookie";
|
||||
// FIXME: remove this in favor of BackOfficeAuthenticationType when the old backoffice auth is no longer necessary
|
||||
public const string NewBackOfficeAuthenticationType = "NewUmbracoBackOffice";
|
||||
public const string NewBackOfficeExternalAuthenticationType = "NewUmbracoExternalCookie";
|
||||
public const string NewBackOfficeTwoFactorAuthenticationType = "NewUmbracoTwoFactorCookie";
|
||||
public const string NewBackOfficeTwoFactorRememberMeAuthenticationType = "NewUmbracoTwoFactorRememberMeCookie";
|
||||
public const string EmptyPasswordPrefix = "___UIDEMPTYPWORD__";
|
||||
|
||||
public const string DefaultMemberTypeAlias = "Member";
|
||||
|
||||
@@ -97,7 +97,6 @@ public static partial class UmbracoBuilderExtensions
|
||||
.Append<Hulu>()
|
||||
.Append<Giphy>()
|
||||
.Append<LottieFiles>();
|
||||
builder.SearchableTrees().Add(() => builder.TypeLoader.GetTypes<ISearchableTree>());
|
||||
builder.BackOfficeAssets();
|
||||
builder.SelectorHandlers().Add(() => builder.TypeLoader.GetTypes<ISelectorHandler>());
|
||||
builder.FilterHandlers().Add(() => builder.TypeLoader.GetTypes<IFilterHandler>());
|
||||
@@ -245,12 +244,6 @@ public static partial class UmbracoBuilderExtensions
|
||||
public static EmbedProvidersCollectionBuilder EmbedProviders(this IUmbracoBuilder builder)
|
||||
=> builder.WithCollectionBuilder<EmbedProvidersCollectionBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the back office searchable tree collection builder
|
||||
/// </summary>
|
||||
public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder)
|
||||
=> builder.WithCollectionBuilder<SearchableTreeCollectionBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the back office custom assets collection builder
|
||||
/// </summary>
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
|
||||
Services.AddUnique<IEventMessagesFactory, DefaultEventMessagesFactory>();
|
||||
Services.AddUnique<IEventMessagesAccessor, HybridEventMessagesAccessor>();
|
||||
Services.AddUnique<ITreeService, TreeService>();
|
||||
|
||||
Services.AddUnique<ISmsSender, NotImplementedSmsSender>();
|
||||
Services.AddUnique<IEmailSender, NotImplementedEmailSender>();
|
||||
|
||||
@@ -369,7 +369,7 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
Services.AddUnique<IWebhookLogService, WebhookLogService>();
|
||||
Services.AddUnique<IWebhookLogFactory, WebhookLogFactory>();
|
||||
Services.AddUnique<IWebhookRequestService, WebhookRequestService>();
|
||||
|
||||
|
||||
// Data type configuration cache
|
||||
Services.AddUnique<IDataTypeConfigurationCache, DataTypeConfigurationCache>();
|
||||
Services.AddNotificationHandler<DataTypeCacheRefresherNotification, DataTypeConfigurationCacheRefresher>();
|
||||
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.Mapping;
|
||||
|
||||
@@ -20,6 +21,9 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
private readonly ContentPropertyBasicMapper<ContentPropertyBasic> _contentPropertyBasicConverter;
|
||||
private readonly ContentPropertyDisplayMapper _contentPropertyDisplayMapper;
|
||||
private readonly ContentPropertyDtoMapper _contentPropertyDtoConverter;
|
||||
private readonly CommonMapper _commonMapper;
|
||||
private readonly ContentBasicSavedStateMapper<ContentPropertyBasic> _basicStateMapper;
|
||||
|
||||
|
||||
public ContentPropertyMapDefinition(
|
||||
ICultureDictionary cultureDictionary,
|
||||
@@ -28,8 +32,10 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
ILocalizedTextService textService,
|
||||
ILoggerFactory loggerFactory,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache)
|
||||
CommonMapper commonMapper)
|
||||
{
|
||||
_commonMapper = commonMapper;
|
||||
_basicStateMapper = new ContentBasicSavedStateMapper<ContentPropertyBasic>();
|
||||
_contentPropertyBasicConverter = new ContentPropertyBasicMapper<ContentPropertyBasic>(
|
||||
dataTypeService,
|
||||
entityService,
|
||||
@@ -49,24 +55,6 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
propertyEditors);
|
||||
}
|
||||
|
||||
[Obsolete("Please use constructor that takes an IDataTypeConfigurationCache. Will be removed in V14.")]
|
||||
public ContentPropertyMapDefinition(
|
||||
ICultureDictionary cultureDictionary,
|
||||
IDataTypeService dataTypeService,
|
||||
IEntityService entityService,
|
||||
ILocalizedTextService textService,
|
||||
ILoggerFactory loggerFactory,
|
||||
PropertyEditorCollection propertyEditors)
|
||||
: this(
|
||||
cultureDictionary,
|
||||
dataTypeService,
|
||||
entityService,
|
||||
textService,
|
||||
loggerFactory,
|
||||
propertyEditors,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IDataTypeConfigurationCache>())
|
||||
{ }
|
||||
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<PropertyGroup, Tab<ContentPropertyDisplay>>(
|
||||
@@ -74,6 +62,8 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
mapper.Define<IProperty, ContentPropertyBasic>((source, context) => new ContentPropertyBasic(), Map);
|
||||
mapper.Define<IProperty, ContentPropertyDto>((source, context) => new ContentPropertyDto(), Map);
|
||||
mapper.Define<IProperty, ContentPropertyDisplay>((source, context) => new ContentPropertyDisplay(), Map);
|
||||
mapper.Define<IContent, ContentItemBasic<ContentPropertyBasic>>((source, context) => new ContentItemBasic<ContentPropertyBasic>(), Map);
|
||||
mapper.Define<IContent, ContentPropertyCollectionDto>((source, context) => new ContentPropertyCollectionDto(), Map);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll -Properties -Alias -Expanded
|
||||
@@ -101,4 +91,81 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
|
||||
// assume this is mapping everything and no MapAll is required
|
||||
_contentPropertyDisplayMapper.Map(source, target, context);
|
||||
|
||||
// Umbraco.Code.MapAll -Alias
|
||||
private void Map(IContent source, ContentItemBasic<ContentPropertyBasic> target, MapperContext context)
|
||||
{
|
||||
target.ContentTypeId = source.ContentType.Id;
|
||||
target.ContentTypeAlias = source.ContentType.Alias;
|
||||
target.CreateDate = source.CreateDate;
|
||||
target.Edited = source.Edited;
|
||||
target.Icon = source.ContentType.Icon;
|
||||
target.Id = source.Id;
|
||||
target.Key = source.Key;
|
||||
target.Name = GetName(source, context);
|
||||
target.Owner = _commonMapper.GetOwner(source, context);
|
||||
target.ParentId = source.ParentId;
|
||||
target.Path = source.Path;
|
||||
target.Properties = context.MapEnumerable<IProperty, ContentPropertyBasic>(source.Properties).WhereNotNull();
|
||||
target.SortOrder = source.SortOrder;
|
||||
target.State = _basicStateMapper.Map(source, context);
|
||||
target.Trashed = source.Trashed;
|
||||
target.Udi =
|
||||
Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key);
|
||||
target.UpdateDate = GetUpdateDate(source, context);
|
||||
target.Updater = _commonMapper.GetCreator(source, context);
|
||||
target.VariesByCulture = source.ContentType.VariesByCulture();
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private static void Map(IContent source, ContentPropertyCollectionDto target, MapperContext context) =>
|
||||
target.Properties = context.MapEnumerable<IProperty, ContentPropertyDto>(source.Properties).WhereNotNull();
|
||||
|
||||
private string? GetName(IContent source, MapperContext context)
|
||||
{
|
||||
// invariant = only 1 name
|
||||
if (!source.ContentType.VariesByCulture())
|
||||
{
|
||||
return source.Name;
|
||||
}
|
||||
|
||||
// variant = depends on culture
|
||||
var culture = context.GetCulture();
|
||||
|
||||
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
|
||||
if (culture == null)
|
||||
{
|
||||
throw new InvalidOperationException("Missing culture in mapping options.");
|
||||
}
|
||||
|
||||
// if we don't have a name for a culture, it means the culture is not available, and
|
||||
// hey we should probably not be mapping it, but it's too late, return a fallback name
|
||||
return source.CultureInfos is not null &&
|
||||
source.CultureInfos.TryGetValue(culture, out ContentCultureInfos name) && !name.Name.IsNullOrWhiteSpace()
|
||||
? name.Name
|
||||
: $"({source.Name})";
|
||||
}
|
||||
|
||||
private DateTime GetUpdateDate(IContent source, MapperContext context)
|
||||
{
|
||||
// invariant = global date
|
||||
if (!source.ContentType.VariesByCulture())
|
||||
{
|
||||
return source.UpdateDate;
|
||||
}
|
||||
|
||||
// variant = depends on culture
|
||||
var culture = context.GetCulture();
|
||||
|
||||
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
|
||||
if (culture == null)
|
||||
{
|
||||
throw new InvalidOperationException("Missing culture in mapping options.");
|
||||
}
|
||||
|
||||
// if we don't have a date for a culture, it means the culture is not available, and
|
||||
// hey we should probably not be mapping it, but it's too late, return a fallback date
|
||||
DateTime? date = source.GetUpdateDate(culture);
|
||||
return date ?? source.UpdateDate;
|
||||
}
|
||||
}
|
||||
|
||||
50
src/Umbraco.Core/Models/Mapping/MediaMapDefinition.cs
Normal file
50
src/Umbraco.Core/Models/Mapping/MediaMapDefinition.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.Mapping;
|
||||
|
||||
/// <summary>
|
||||
/// Declares model mappings for media.
|
||||
/// </summary>
|
||||
public class MediaMapDefinition : IMapDefinition
|
||||
{
|
||||
private readonly CommonMapper _commonMapper;
|
||||
|
||||
public MediaMapDefinition(CommonMapper commonMapper)
|
||||
{
|
||||
_commonMapper = commonMapper;
|
||||
}
|
||||
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<IMedia, ContentPropertyCollectionDto>((source, context) => new ContentPropertyCollectionDto(), Map);
|
||||
mapper.Define<IMedia, ContentItemBasic<ContentPropertyBasic>>((source, context) => new ContentItemBasic<ContentPropertyBasic>(), Map);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private static void Map(IMedia source, ContentPropertyCollectionDto target, MapperContext context) =>
|
||||
target.Properties = context.MapEnumerable<IProperty, ContentPropertyDto>(source.Properties).WhereNotNull();
|
||||
|
||||
// Umbraco.Code.MapAll -Edited -Updater -Alias
|
||||
private void Map(IMedia source, ContentItemBasic<ContentPropertyBasic> target, MapperContext context)
|
||||
{
|
||||
target.ContentTypeId = source.ContentType.Id;
|
||||
target.ContentTypeAlias = source.ContentType.Alias;
|
||||
target.CreateDate = source.CreateDate;
|
||||
target.Icon = source.ContentType.Icon;
|
||||
target.Id = source.Id;
|
||||
target.Key = source.Key;
|
||||
target.Name = source.Name;
|
||||
target.Owner = _commonMapper.GetOwner(source, context);
|
||||
target.ParentId = source.ParentId;
|
||||
target.Path = source.Path;
|
||||
target.Properties = context.MapEnumerable<IProperty, ContentPropertyBasic>(source.Properties).WhereNotNull();
|
||||
target.SortOrder = source.SortOrder;
|
||||
target.State = null;
|
||||
target.Trashed = source.Trashed;
|
||||
target.Udi = Udi.Create(Constants.UdiEntityType.Media, source.Key);
|
||||
target.UpdateDate = source.UpdateDate;
|
||||
target.VariesByCulture = source.ContentType.VariesByCulture();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,23 @@
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.Mapping;
|
||||
|
||||
/// <inheritdoc />
|
||||
public class MemberMapDefinition : IMapDefinition
|
||||
{
|
||||
private readonly CommonMapper _commonMapper;
|
||||
|
||||
public MemberMapDefinition(CommonMapper commonMapper) => _commonMapper = commonMapper;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DefineMaps(IUmbracoMapper mapper) => mapper.Define<MemberSave, IMember>(Map);
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<MemberSave, IMember>(Map);
|
||||
mapper.Define<IMember, MemberBasic>((source, context) => new MemberBasic(), Map);
|
||||
mapper.Define<IMember, ContentPropertyCollectionDto>((source, context) => new ContentPropertyCollectionDto(), Map);
|
||||
}
|
||||
|
||||
private static void Map(MemberSave source, IMember target, MapperContext context)
|
||||
{
|
||||
@@ -28,4 +38,36 @@ public class MemberMapDefinition : IMapDefinition
|
||||
|
||||
// TODO: add groups as required
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll -Trashed -Edited -Updater -Alias -VariesByCulture
|
||||
private void Map(IMember source, MemberBasic target, MapperContext context)
|
||||
{
|
||||
target.ContentTypeId = source.ContentType.Id;
|
||||
target.ContentTypeAlias = source.ContentType.Alias;
|
||||
target.CreateDate = source.CreateDate;
|
||||
target.Email = source.Email;
|
||||
target.Icon = source.ContentType.Icon;
|
||||
target.Id = int.MaxValue;
|
||||
target.Key = source.Key;
|
||||
target.Name = source.Name;
|
||||
target.Owner = _commonMapper.GetOwner(source, context);
|
||||
target.ParentId = source.ParentId;
|
||||
target.Path = source.Path;
|
||||
target.Properties = context.MapEnumerable<IProperty, ContentPropertyBasic>(source.Properties).WhereNotNull();
|
||||
target.SortOrder = source.SortOrder;
|
||||
target.State = null;
|
||||
target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key);
|
||||
target.UpdateDate = source.UpdateDate;
|
||||
target.Username = source.Username;
|
||||
target.FailedPasswordAttempts = source.FailedPasswordAttempts;
|
||||
target.Approved = source.IsApproved;
|
||||
target.LockedOut = source.IsLockedOut;
|
||||
target.LastLockoutDate = source.LastLockoutDate;
|
||||
target.LastLoginDate = source.LastLoginDate;
|
||||
target.LastPasswordChangeDate = source.LastPasswordChangeDate;
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private static void Map(IMember source, ContentPropertyCollectionDto target, MapperContext context) =>
|
||||
target.Properties = context.MapEnumerable<IProperty, ContentPropertyDto>(source.Properties).WhereNotNull();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace Umbraco.Cms.Core.Security;
|
||||
|
||||
public class BackOfficeAuthenticationTypeSettings
|
||||
{
|
||||
public string AuthenticationType { get; set; } = Constants.Security.NewBackOfficeAuthenticationType;
|
||||
public string ExternalAuthenticationType { get; set; } = Constants.Security.NewBackOfficeExternalAuthenticationType;
|
||||
public string TwoFactorAuthenticationType { get; set; } = Constants.Security.NewBackOfficeTwoFactorAuthenticationType;
|
||||
public string TwoFactorRememberMeAuthenticationType { get; set; } = Constants.Security.NewBackOfficeTwoFactorRememberMeAuthenticationType;
|
||||
public string AuthenticationType { get; set; } = Constants.Security.BackOfficeAuthenticationType;
|
||||
public string ExternalAuthenticationType { get; set; } = Constants.Security.BackOfficeExternalAuthenticationType;
|
||||
public string TwoFactorAuthenticationType { get; set; } = Constants.Security.BackOfficeTwoFactorAuthenticationType;
|
||||
public string TwoFactorRememberMeAuthenticationType { get; set; } = Constants.Security.BackOfficeTwoFactorRememberMeAuthenticationType;
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
public interface IIconService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the svg string for the icon name found at the global icons path
|
||||
/// </summary>
|
||||
/// <param name="iconName"></param>
|
||||
/// <returns></returns>
|
||||
IconModel? GetIcon(string iconName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all svg icons found at at the global icons path.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IReadOnlyDictionary<string, string>? GetIcons();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using Umbraco.Cms.Core.Trees;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a service which manages section trees.
|
||||
/// </summary>
|
||||
public interface ITreeService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a tree.
|
||||
/// </summary>
|
||||
/// <param name="treeAlias">The tree alias.</param>
|
||||
Tree? GetByAlias(string treeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all trees.
|
||||
/// </summary>
|
||||
IEnumerable<Tree> GetAll(TreeUse use = TreeUse.Main);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all trees for a section.
|
||||
/// </summary>
|
||||
IEnumerable<Tree> GetBySection(string sectionAlias, TreeUse use = TreeUse.Main);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all trees for a section, grouped.
|
||||
/// </summary>
|
||||
IDictionary<string, IEnumerable<Tree>> GetBySectionGrouped(string sectionAlias, TreeUse use = TreeUse.Main);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using Umbraco.Cms.Core.Trees;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="ITreeService" />.
|
||||
/// </summary>
|
||||
public class TreeService : ITreeService
|
||||
{
|
||||
private readonly TreeCollection _treeCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TreeService" /> class.
|
||||
/// </summary>
|
||||
/// <param name="treeCollection"></param>
|
||||
public TreeService(TreeCollection treeCollection) => _treeCollection = treeCollection;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Tree? GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(x => x.TreeAlias == treeAlias);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Tree> GetAll(TreeUse use = TreeUse.Main)
|
||||
|
||||
// use HasFlagAny: if use is Main|Dialog, we want to return Main *and* Dialog trees
|
||||
=> _treeCollection.Where(x => x.TreeUse.HasFlagAny(use));
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Tree> GetBySection(string sectionAlias, TreeUse use = TreeUse.Main)
|
||||
|
||||
// use HasFlagAny: if use is Main|Dialog, we want to return Main *and* Dialog trees
|
||||
=> _treeCollection.Where(x => x.SectionAlias.InvariantEquals(sectionAlias) && x.TreeUse.HasFlagAny(use))
|
||||
.OrderBy(x => x.SortOrder).ToList();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, IEnumerable<Tree>>
|
||||
GetBySectionGrouped(string sectionAlias, TreeUse use = TreeUse.Main) =>
|
||||
GetBySection(sectionAlias, use).GroupBy(x => x.TreeGroup).ToDictionary(
|
||||
x => x.Key ?? string.Empty,
|
||||
x => (IEnumerable<Tree>)x.ToArray());
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Trees;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class SearchableTreeAttribute : Attribute
|
||||
{
|
||||
public const int DefaultSortOrder = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// This constructor will assume that the method name equals `format(searchResult, appAlias, treeAlias)`.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">Name of the service.</param>
|
||||
public SearchableTreeAttribute(string serviceName)
|
||||
: this(serviceName, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This constructor defines both the Angular service and method name to use.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">Name of the service.</param>
|
||||
/// <param name="methodName">Name of the method.</param>
|
||||
public SearchableTreeAttribute(string serviceName, string methodName)
|
||||
: this(serviceName, methodName, DefaultSortOrder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This constructor defines both the Angular service and method name to use and explicitly defines a sort order for
|
||||
/// the results
|
||||
/// </summary>
|
||||
/// <param name="serviceName">Name of the service.</param>
|
||||
/// <param name="methodName">Name of the method.</param>
|
||||
/// <param name="sortOrder">The sort order.</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// serviceName
|
||||
/// or
|
||||
/// methodName
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">Value can't be empty or consist only of white-space characters. - serviceName</exception>
|
||||
public SearchableTreeAttribute(string serviceName, string methodName, int sortOrder)
|
||||
{
|
||||
if (serviceName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serviceName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(serviceName))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Value can't be empty or consist only of white-space characters.",
|
||||
nameof(serviceName));
|
||||
}
|
||||
|
||||
ServiceName = serviceName;
|
||||
MethodName = methodName ?? throw new ArgumentNullException(nameof(methodName));
|
||||
SortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public string ServiceName { get; }
|
||||
|
||||
public string MethodName { get; }
|
||||
|
||||
public int SortOrder { get; }
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Trees;
|
||||
|
||||
public class SearchableTreeCollection : BuilderCollectionBase<ISearchableTree>
|
||||
{
|
||||
private readonly Dictionary<string, SearchableApplicationTree> _dictionary;
|
||||
|
||||
public SearchableTreeCollection(Func<IEnumerable<ISearchableTree>> items, ITreeService treeService)
|
||||
: base(items) =>
|
||||
_dictionary = CreateDictionary(treeService);
|
||||
|
||||
public IReadOnlyDictionary<string, SearchableApplicationTree> SearchableApplicationTrees => _dictionary;
|
||||
|
||||
public SearchableApplicationTree this[string key] => _dictionary[key];
|
||||
|
||||
private Dictionary<string, SearchableApplicationTree> CreateDictionary(ITreeService treeService)
|
||||
{
|
||||
Tree[] appTrees = treeService.GetAll()
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToArray();
|
||||
var dictionary = new Dictionary<string, SearchableApplicationTree>(StringComparer.OrdinalIgnoreCase);
|
||||
ISearchableTree[] searchableTrees = this.ToArray();
|
||||
foreach (Tree appTree in appTrees)
|
||||
{
|
||||
ISearchableTree? found = searchableTrees.FirstOrDefault(x => x.TreeAlias.InvariantEquals(appTree.TreeAlias));
|
||||
if (found != null)
|
||||
{
|
||||
SearchableTreeAttribute? searchableTreeAttribute =
|
||||
found.GetType().GetCustomAttribute<SearchableTreeAttribute>(false);
|
||||
dictionary[found.TreeAlias] = new SearchableApplicationTree(
|
||||
appTree.SectionAlias,
|
||||
appTree.TreeAlias,
|
||||
searchableTreeAttribute?.SortOrder ?? SearchableTreeAttribute.DefaultSortOrder,
|
||||
searchableTreeAttribute?.ServiceName ?? string.Empty,
|
||||
searchableTreeAttribute?.MethodName ?? string.Empty,
|
||||
found);
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Core.Trees;
|
||||
|
||||
public class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase<SearchableTreeCollectionBuilder,
|
||||
SearchableTreeCollection, ISearchableTree>
|
||||
{
|
||||
protected override SearchableTreeCollectionBuilder This => this;
|
||||
|
||||
// per request because generally an instance of ISearchableTree is a controller
|
||||
protected override ServiceLifetime CollectionLifetime => ServiceLifetime.Scoped;
|
||||
}
|
||||
Reference in New Issue
Block a user