Refactors the usage of ICultureDictionary so its injectable, removes more uses of Current, removes unused methods relying on System.Web

This commit is contained in:
Shannon
2019-11-22 13:13:19 +11:00
parent e51a3efe15
commit 3dbebfb153
30 changed files with 140 additions and 155 deletions

View File

@@ -4,7 +4,14 @@ namespace Umbraco.Core.Services
{
public interface IPropertyValidationService
{
/// <summary>
/// Validates the content item's properties pass validation rules
/// </summary>
bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact);
/// <summary>
/// Gets a value indicating whether the property has valid values.
/// </summary>
bool IsPropertyValid(IProperty property, string culture = "*", string segment = "*");
}
}
}

View File

@@ -69,24 +69,7 @@ namespace Umbraco.Core.Services
.ToDictionary(keyvals => keyvals.index, keyvals => keyvals.value);
}
private static ICultureDictionary _cultureDictionary;
/// <summary>
/// TODO: We need to refactor how we work with ICultureDictionary - this is supposed to be the 'fast' way to
/// do readonly access to the Dictionary without using the ILocalizationService. See TODO Notes in `DefaultCultureDictionary`
/// Also NOTE that the ICultureDictionary is based on the ILocalizationService not the ILocalizedTextService (which is used
/// only for the localization files - not the dictionary)
/// </summary>
/// <param name="manager"></param>
/// <param name="text"></param>
/// <returns></returns>
internal static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, string text)
{
var cultureDictionary = CultureDictionary;
return manager.UmbracoDictionaryTranslate(text, cultureDictionary);
}
private static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, string text, ICultureDictionary cultureDictionary)
public static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, ICultureDictionary cultureDictionary, string text)
{
if (text == null)
return null;
@@ -105,7 +88,5 @@ namespace Umbraco.Core.Services
return value.StartsWith("[") ? text : value;
}
private static ICultureDictionary CultureDictionary
=> _cultureDictionary ?? (_cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary());
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -53,11 +52,6 @@ namespace Umbraco.Core.Services
return HasAccess(entry, username, currentMemberRoles);
}
public static bool HasAccess(this IPublicAccessService publicAccessService, string path, MembershipUser member, RoleProvider roleProvider)
{
return publicAccessService.HasAccess(path, member.UserName, roleProvider.GetRolesForUser);
}
/// <summary>
/// Checks if the member with the specified username has access to the path which is also based on the passed in roles for the member
/// </summary>

View File

@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Web.Security;
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Services
@@ -69,40 +68,5 @@ namespace Umbraco.Core.Services
userService.ReplaceUserGroupPermissions(groupId, new char[] { });
}
/// <summary>
/// Maps a custom provider's information to an umbraco user account
/// </summary>
/// <param name="userService"></param>
/// <param name="member"></param>
/// <remarks>
/// To maintain compatibility we have to check the login name if the provider key lookup fails but otherwise
/// we'll store the provider user key in the login column.
/// </remarks>
internal static IUser CreateUserMappingForCustomProvider(this IUserService userService, MembershipUser member)
{
if (member == null) throw new ArgumentNullException("member");
var valToLookup = member.ProviderUserKey == null ? member.UserName : member.ProviderUserKey.ToString();
var found = userService.GetByUsername(valToLookup);
if (found == null && member.ProviderUserKey != null)
{
//try by username
found = userService.GetByUsername(member.UserName);
}
if (found == null)
{
var user = new User(
member.UserName,
member.Email ?? Guid.NewGuid().ToString("N") + "@example.com", //email cannot be empty
member.ProviderUserKey == null ? member.UserName : member.ProviderUserKey.ToString(),
Guid.NewGuid().ToString("N")); //pass cannot be empty
userService.Save(user);
return user;
}
return found;
}
}
}

View File

@@ -27,6 +27,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
composition.RegisterUnique<IdkMap>();
// register the services
composition.RegisterUnique<IPropertyValidationService, PropertyValidationService>();
composition.RegisterUnique<IKeyValueService, KeyValueService>();
composition.RegisterUnique<IPublicAccessService, PublicAccessService>();
composition.RegisterUnique<IDomainService, DomainService>();

View File

@@ -91,7 +91,7 @@ namespace Umbraco.Core
public static void SetCultureDictionaryFactory<T>(this Composition composition)
where T : ICultureDictionaryFactory
{
composition.RegisterUnique<ICultureDictionaryFactory, T>();
composition.RegisterUnique<ICultureDictionaryFactory, T>();
}
/// <summary>

View File

@@ -8,7 +8,6 @@ using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Scoping;
@@ -27,7 +26,7 @@ namespace Umbraco.Core.Services.Implement
private readonly IContentTypeRepository _contentTypeRepository;
private readonly IDocumentBlueprintRepository _documentBlueprintRepository;
private readonly ILanguageRepository _languageRepository;
private readonly IPropertyValidationService _propertyValidationService;
private readonly Lazy<IPropertyValidationService> _propertyValidationService;
private IQuery<IContent> _queryNotTrashed;
#region Constructors
@@ -36,7 +35,7 @@ namespace Umbraco.Core.Services.Implement
IEventMessagesFactory eventMessagesFactory,
IDocumentRepository documentRepository, IEntityRepository entityRepository, IAuditRepository auditRepository,
IContentTypeRepository contentTypeRepository, IDocumentBlueprintRepository documentBlueprintRepository, ILanguageRepository languageRepository,
IPropertyValidationService propertyValidationService)
Lazy<IPropertyValidationService> propertyValidationService)
: base(provider, logger, eventMessagesFactory)
{
_documentRepository = documentRepository;
@@ -1404,7 +1403,7 @@ namespace Umbraco.Core.Services.Implement
//publish the culture values and validate the property values, if validation fails, log the invalid properties so the develeper has an idea of what has failed
IProperty[] invalidProperties = null;
var impact = CultureImpact.Explicit(culture, IsDefaultCulture(allLangs, culture));
var tryPublish = d.PublishCulture(impact) && _propertyValidationService.IsPropertyDataValid(d, out invalidProperties, impact);
var tryPublish = d.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(d, out invalidProperties, impact);
if (invalidProperties != null && invalidProperties.Length > 0)
Logger.Warn<ContentService>("Scheduled publishing will fail for document {DocumentId} and culture {Culture} because of invalid properties {InvalidProperties}",
d.Id, culture, string.Join(",", invalidProperties.Select(x => x.Alias)));
@@ -1505,12 +1504,12 @@ namespace Umbraco.Core.Services.Implement
return culturesToPublish.All(culture =>
{
var impact = CultureImpact.Create(culture, IsDefaultCulture(allLangs, culture), content);
return content.PublishCulture(impact) && _propertyValidationService.IsPropertyDataValid(content, out _, impact);
return content.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(content, out _, impact);
});
}
return content.PublishCulture(CultureImpact.Invariant)
&& _propertyValidationService.IsPropertyDataValid(content, out _, CultureImpact.Invariant);
&& _propertyValidationService.Value.IsPropertyDataValid(content, out _, CultureImpact.Invariant);
}
// utility 'ShouldPublish' func used by SaveAndPublishBranch
@@ -2603,7 +2602,7 @@ namespace Umbraco.Core.Services.Implement
//validate the property values
IProperty[] invalidProperties = null;
if (!impactsToPublish.All(x => _propertyValidationService.IsPropertyDataValid(content, out invalidProperties, x)))
if (!impactsToPublish.All(x => _propertyValidationService.Value.IsPropertyDataValid(content, out invalidProperties, x)))
return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, content)
{
InvalidProperties = invalidProperties

View File

@@ -15,9 +15,7 @@ namespace Umbraco.Core.Services
_dataTypeService = dataTypeService;
}
/// <summary>
/// Validates the content item's properties pass validation rules
/// </summary>
/// <inheritdoc />
public bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact)
{
// select invalid properties
@@ -50,9 +48,7 @@ namespace Umbraco.Core.Services
return invalidProperties.Length == 0;
}
/// <summary>
/// Gets a value indicating whether the property has valid values.
/// </summary>
/// <inheritdoc />
public bool IsPropertyValid(IProperty property, string culture = "*", string segment = "*")
{
//NOTE - the pvalue and vvalues logic in here is borrowed directly from the Property.Values setter so if you are wondering what that's all about, look there.

View File

@@ -235,7 +235,7 @@
<Compile Include="Serialization\JsonNetSerializer.cs" />
<Compile Include="Services\Changes\ContentTypeChange.cs" />
<Compile Include="Services\Changes\ContentTypeChangeExtensions.cs" />
<Compile Include="Services\LocalizedTextServiceExtensions.cs" />
<Compile Include="Services\Implement\PropertyValidationService.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="Strings\DefaultUrlSegmentProvider.cs" />
<Compile Include="Strings\IUrlSegmentProvider.cs" />
@@ -793,7 +793,6 @@
<Compile Include="Services\Implement\NotificationService.cs" />
<Compile Include="Services\Implement\PackagingService.cs" />
<Compile Include="Services\Implement\PublicAccessService.cs" />
<Compile Include="Services\PublicAccessServiceExtensions.cs" />
<Compile Include="Services\Implement\RedirectUrlService.cs" />
<Compile Include="Services\Implement\RelationService.cs" />
<Compile Include="Services\Implement\RepositoryService.cs" />
@@ -801,7 +800,6 @@
<Compile Include="Services\Implement\ServerRegistrationService.cs" />
<Compile Include="Services\Implement\TagService.cs" />
<Compile Include="Services\Implement\UserService.cs" />
<Compile Include="Services\UserServiceExtensions.cs" />
<Compile Include="Compose\ManifestWatcherComponent.cs" />
<Compile Include="Compose\RelateOnCopyComponent.cs" />
<Compile Include="Compose\RelateOnTrashComponent.cs" />

View File

@@ -152,10 +152,13 @@ namespace Umbraco.Tests.TestHelpers
var runtimeState = Mock.Of<IRuntimeState>();
var idkMap = new IdkMap(scopeProvider);
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var localizationService = GetLazyService<ILocalizationService>(factory, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo<IDictionaryRepository>(c), GetRepo<IAuditRepository>(c), GetRepo<ILanguageRepository>(c)));
var userService = GetLazyService<IUserService>(factory, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo<IUserRepository>(c), GetRepo<IUserGroupRepository>(c),globalSettings));
var dataTypeService = GetLazyService<IDataTypeService>(factory, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo<IDataTypeRepository>(c), GetRepo<IDataTypeContainerRepository>(c), GetRepo<IAuditRepository>(c), GetRepo<IEntityRepository>(c), GetRepo<IContentTypeRepository>(c)));
var contentService = GetLazyService<IContentService>(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo<IDocumentRepository>(c), GetRepo<IEntityRepository>(c), GetRepo<IAuditRepository>(c), GetRepo<IContentTypeRepository>(c), GetRepo<IDocumentBlueprintRepository>(c), GetRepo<ILanguageRepository>(c)));
var propertyValidationService = new Lazy<IPropertyValidationService>(() => new PropertyValidationService(propertyEditorCollection, dataTypeService.Value));
var contentService = GetLazyService<IContentService>(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo<IDocumentRepository>(c), GetRepo<IEntityRepository>(c), GetRepo<IAuditRepository>(c), GetRepo<IContentTypeRepository>(c), GetRepo<IDocumentBlueprintRepository>(c), GetRepo<ILanguageRepository>(c), propertyValidationService));
var notificationService = GetLazyService<INotificationService>(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, ioHelper, GetRepo<INotificationsRepository>(c), globalSettings, umbracoSettings.Content));
var serverRegistrationService = GetLazyService<IServerRegistrationService>(factory, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo<IServerRegistrationRepository>(c)));
var memberGroupService = GetLazyService<IMemberGroupService>(factory, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo<IMemberGroupRepository>(c)));
@@ -170,8 +173,7 @@ namespace Umbraco.Tests.TestHelpers
var macroService = GetLazyService<IMacroService>(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo<IMacroRepository>(c), GetRepo<IAuditRepository>(c)));
var packagingService = GetLazyService<IPackagingService>(factory, c =>
{
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
{
var compiledPackageXmlParser = new CompiledPackageXmlParser(new ConflictingPackageData(macroService.Value, fileService.Value), globalSettings);
return new PackagingService(
auditService.Value,

View File

@@ -42,6 +42,8 @@ using Umbraco.Web.Composing.CompositionExtensions;
using Umbraco.Web.Sections;
using Current = Umbraco.Core.Composing.Current;
using FileSystems = Umbraco.Core.IO.FileSystems;
using Umbraco.Web.Dictionary;
using Umbraco.Core.Dictionary;
namespace Umbraco.Tests.Testing
{
@@ -131,7 +133,7 @@ namespace Umbraco.Tests.Testing
// get/merge the attributes marking the method and/or the classes
Options = TestOptionAttributeBase.GetTestOptions<UmbracoTestAttribute>();
// FIXME: align to runtimes & components - don't redo everything here
// FIXME: align to runtimes & components - don't redo everything here !!!! Yes this is getting painful
var (logger, profiler) = GetLoggers(Options.Logger);
var proflogger = new ProfilingLogger(logger, profiler);
@@ -233,7 +235,8 @@ namespace Umbraco.Tests.Testing
Composition.RegisterUnique<IContentLastChanceFinder, TestLastChanceFinder>();
Composition.RegisterUnique<IVariationContextAccessor, TestVariationContextAccessor>();
Composition.RegisterUnique<IPublishedSnapshotAccessor, TestPublishedSnapshotAccessor>();
Composition.SetCultureDictionaryFactory<DefaultCultureDictionaryFactory>();
Composition.Register(f => f.GetInstance<ICultureDictionaryFactory>().CreateDictionary(), Lifetime.Singleton);
// register back office sections in the order we want them rendered
Composition.WithCollectionBuilder<SectionCollectionBuilder>().Append<ContentSection>()
.Append<MediaSection>()

View File

@@ -21,8 +21,6 @@ using Umbraco.Tests.Testing;
using Umbraco.Web;
using Umbraco.Web.Editors;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.PublishedCache;
using Task = System.Threading.Tasks.Task;
using Umbraco.Core.Dictionary;
using Umbraco.Web.PropertyEditors;
@@ -260,6 +258,7 @@ namespace Umbraco.Tests.Web.Controllers
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var controller = new ContentController(
Factory.GetInstance<ICultureDictionary>(),
propertyEditorCollection,
Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,
@@ -293,6 +292,7 @@ namespace Umbraco.Tests.Web.Controllers
{
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var controller = new ContentController(
Factory.GetInstance<ICultureDictionary>(),
propertyEditorCollection,
Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,
@@ -334,6 +334,7 @@ namespace Umbraco.Tests.Web.Controllers
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var controller = new ContentController(
Factory.GetInstance<ICultureDictionary>(),
propertyEditorCollection,
Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,
@@ -380,6 +381,7 @@ namespace Umbraco.Tests.Web.Controllers
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var controller = new ContentController(
Factory.GetInstance<ICultureDictionary>(),
propertyEditorCollection,
Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,
@@ -418,6 +420,7 @@ namespace Umbraco.Tests.Web.Controllers
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var controller = new ContentController(
Factory.GetInstance<ICultureDictionary>(),
propertyEditorCollection,
Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,
@@ -462,6 +465,7 @@ namespace Umbraco.Tests.Web.Controllers
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var controller = new ContentController(
Factory.GetInstance<ICultureDictionary>(),
propertyEditorCollection,
Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,

View File

@@ -24,22 +24,23 @@ namespace Umbraco.Web.Dictionary
private readonly IAppCache _requestCache;
private readonly CultureInfo _specificCulture;
public DefaultCultureDictionary()
: this(Current.Services.LocalizationService, Current.AppCaches.RequestCache)
{ }
/// <summary>
/// Default constructor which will use the current thread's culture
/// </summary>
/// <param name="localizationService"></param>
/// <param name="requestCache"></param>
public DefaultCultureDictionary(ILocalizationService localizationService, IAppCache requestCache)
{
_localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
_requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache));
}
public DefaultCultureDictionary(CultureInfo specificCulture)
: this(Current.Services.LocalizationService, Current.AppCaches.RequestCache)
{
_specificCulture = specificCulture ?? throw new ArgumentNullException(nameof(specificCulture));
}
/// <summary>
/// Constructor for testing to specify a static culture
/// </summary>
/// <param name="specificCulture"></param>
/// <param name="localizationService"></param>
/// <param name="requestCache"></param>
public DefaultCultureDictionary(CultureInfo specificCulture, ILocalizationService localizationService, IAppCache requestCache)
{
_localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));

View File

@@ -1,4 +1,7 @@
namespace Umbraco.Web.Dictionary
using Umbraco.Core.Cache;
using Umbraco.Core.Services;
namespace Umbraco.Web.Dictionary
{
/// <summary>
/// A culture dictionary factory used to create an Umbraco.Core.Dictionary.ICultureDictionary.
@@ -8,9 +11,18 @@
/// </remarks>
internal class DefaultCultureDictionaryFactory : Umbraco.Core.Dictionary.ICultureDictionaryFactory
{
private readonly ILocalizationService _localizationService;
private readonly AppCaches _appCaches;
public DefaultCultureDictionaryFactory(ILocalizationService localizationService, AppCaches appCaches)
{
_localizationService = localizationService;
_appCaches = appCaches;
}
public Umbraco.Core.Dictionary.ICultureDictionary CreateDictionary()
{
return new DefaultCultureDictionary();
return new DefaultCultureDictionary(_localizationService, _appCaches.RequestCache);
}
}
}

View File

@@ -15,7 +15,6 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Models.Mapping;
@@ -37,6 +36,7 @@ using Umbraco.Core.Persistence;
using Umbraco.Core.Security;
using Umbraco.Web.Routing;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Dictionary;
namespace Umbraco.Web.Editors
{
@@ -57,8 +57,8 @@ namespace Umbraco.Web.Editors
public object Domains { get; private set; }
public ContentController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
public ContentController(ICultureDictionary cultureDictionary, PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
_allLangs = new Lazy<IDictionary<string, ILanguage>>(() => Services.LocalizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase));
@@ -357,10 +357,10 @@ namespace Umbraco.Web.Editors
var emptyContent = Services.ContentService.Create("", parentId, contentType.Alias, Security.GetUserId().ResultOr(0));
var mapped = MapToDisplay(emptyContent);
// translate the content type name if applicable
mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(mapped.ContentTypeName);
mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(CultureDictionary, mapped.ContentTypeName);
// if your user type doesn't have access to the Settings section it would not get this property mapped
if (mapped.DocumentType != null)
mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(mapped.DocumentType.Name);
mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(CultureDictionary, mapped.DocumentType.Name);
//remove the listview app if it exists
mapped.ContentApps = mapped.ContentApps.Where(x => x.Alias != "umbListView").ToList();

View File

@@ -6,6 +6,7 @@ using System.Web.Http;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
@@ -26,9 +27,12 @@ namespace Umbraco.Web.Editors
[JsonDateTimeFormatAttribute]
public abstract class ContentControllerBase : BackOfficeNotificationsController
{
protected ContentControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
protected ICultureDictionary CultureDictionary { get; }
protected ContentControllerBase(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
CultureDictionary = cultureDictionary;
}
protected HttpResponseMessage HandleContentNotFound(object id, bool throwException = true)

View File

@@ -52,14 +52,14 @@ namespace Umbraco.Web.Editors
private readonly IScopeProvider _scopeProvider;
public ContentTypeController(IEntityXmlSerializer serializer,
ICultureDictionaryFactory cultureDictionaryFactory,
ICultureDictionary cultureDictionary,
IGlobalSettings globalSettings,
IUmbracoContextAccessor umbracoContextAccessor,
ISqlContext sqlContext, PropertyEditorCollection propertyEditors,
ServiceContext services, AppCaches appCaches,
IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper,
IScopeProvider scopeProvider)
: base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
: base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
_serializer = serializer;
_propertyEditors = propertyEditors;
@@ -438,8 +438,8 @@ namespace Umbraco.Web.Editors
var localizedTextService = Services.TextService;
foreach (var basic in basics)
{
basic.Name = localizedTextService.UmbracoDictionaryTranslate(basic.Name);
basic.Description = localizedTextService.UmbracoDictionaryTranslate(basic.Description);
basic.Name = localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, basic.Name);
basic.Description = localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, basic.Description);
}
//map the blueprints

View File

@@ -28,16 +28,13 @@ namespace Umbraco.Web.Editors
public abstract class ContentTypeControllerBase<TContentType> : UmbracoAuthorizedJsonController
where TContentType : class, IContentTypeComposition
{
private readonly ICultureDictionaryFactory _cultureDictionaryFactory;
private ICultureDictionary _cultureDictionary;
protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
protected ContentTypeControllerBase(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
_cultureDictionaryFactory = cultureDictionaryFactory;
CultureDictionary = cultureDictionary;
}
protected ICultureDictionary CultureDictionary { get; }
/// <summary>
/// Returns the available composite content types for a given content type
@@ -551,9 +548,6 @@ namespace Umbraco.Web.Editors
forDisplay.Errors = ModelState.ToErrorDictionary();
return new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
}
private ICultureDictionary CultureDictionary
=> _cultureDictionary ?? (_cultureDictionary = _cultureDictionaryFactory.CreateDictionary());
}
}
}

View File

@@ -36,6 +36,7 @@ using Umbraco.Web.ContentApps;
using Umbraco.Web.Editors.Binders;
using Umbraco.Web.Editors.Filters;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Dictionary;
namespace Umbraco.Web.Editors
{
@@ -48,8 +49,8 @@ namespace Umbraco.Web.Editors
[MediaControllerControllerConfiguration]
public class MediaController : ContentControllerBase
{
public MediaController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
public MediaController(ICultureDictionary cultureDictionary, PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
}

View File

@@ -36,8 +36,8 @@ namespace Umbraco.Web.Editors
[MediaTypeControllerControllerConfiguration]
public class MediaTypeController : ContentTypeControllerBase<IMediaType>
{
public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
public MediaTypeController(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
}

View File

@@ -30,6 +30,7 @@ using Umbraco.Web.ContentApps;
using Umbraco.Web.Editors.Binders;
using Umbraco.Web.Editors.Filters;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Dictionary;
namespace Umbraco.Web.Editors
{
@@ -38,12 +39,12 @@ namespace Umbraco.Web.Editors
/// access to ALL of the methods on this controller will need access to the member application.
/// </remarks>
[PluginController("UmbracoApi")]
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Members)]
[UmbracoApplicationAuthorize(Constants.Applications.Members)]
[OutgoingNoHyphenGuidFormat]
public class MemberController : ContentControllerBase
{
public MemberController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
public MemberController(ICultureDictionary cultureDictionary, PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
}

View File

@@ -29,8 +29,8 @@ namespace Umbraco.Web.Editors
[UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})]
public class MemberTypeController : ContentTypeControllerBase<IMemberType>
{
public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
public MemberTypeController(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
: base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
{
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
@@ -18,6 +19,7 @@ namespace Umbraco.Web.Models.Mapping
internal class ContentMapDefinition : IMapDefinition
{
private readonly CommonMapper _commonMapper;
private readonly ICultureDictionary _cultureDictionary;
private readonly ILocalizedTextService _localizedTextService;
private readonly IContentService _contentService;
private readonly IContentTypeService _contentTypeService;
@@ -32,11 +34,12 @@ namespace Umbraco.Web.Models.Mapping
private readonly ContentBasicSavedStateMapper<ContentPropertyBasic> _basicStateMapper;
private readonly ContentVariantMapper _contentVariantMapper;
public ContentMapDefinition(CommonMapper commonMapper, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService,
public ContentMapDefinition(CommonMapper commonMapper, ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService,
IFileService fileService, IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, ILocalizationService localizationService, ILogger logger,
IUserService userService)
{
_commonMapper = commonMapper;
_cultureDictionary = cultureDictionary;
_localizedTextService = localizedTextService;
_contentService = contentService;
_contentTypeService = contentTypeService;
@@ -47,7 +50,7 @@ namespace Umbraco.Web.Models.Mapping
_logger = logger;
_userService = userService;
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IContent>(localizedTextService);
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IContent>(cultureDictionary, localizedTextService);
_stateMapper = new ContentSavedStateMapper<ContentPropertyDisplay>();
_basicStateMapper = new ContentBasicSavedStateMapper<ContentPropertyBasic>();
_contentVariantMapper = new ContentVariantMapper(_localizationService);
@@ -75,7 +78,7 @@ namespace Umbraco.Web.Models.Mapping
target.ContentApps = _commonMapper.GetContentApps(source);
target.ContentTypeId = source.ContentType.Id;
target.ContentTypeAlias = source.ContentType.Alias;
target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(source.ContentType.Name);
target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, source.ContentType.Name);
target.DocumentType = _commonMapper.GetContentType(source, context);
target.Icon = source.ContentType.Icon;
target.Id = source.Id;
@@ -231,7 +234,7 @@ namespace Umbraco.Web.Models.Mapping
return contentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(t.Name));
.ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, t.Name));
}
private string GetDefaultTemplate(IContent source)

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Logging;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
@@ -12,11 +13,13 @@ namespace Umbraco.Web.Models.Mapping
/// </summary>
internal class ContentPropertyDisplayMapper : ContentPropertyBasicMapper<ContentPropertyDisplay>
{
private readonly ICultureDictionary _cultureDictionary;
private readonly ILocalizedTextService _textService;
public ContentPropertyDisplayMapper(IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors)
public ContentPropertyDisplayMapper(ICultureDictionary cultureDictionary, IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors)
: base(dataTypeService, entityService, logger, propertyEditors)
{
_cultureDictionary = cultureDictionary;
_textService = textService;
}
public override void Map(IProperty originalProp, ContentPropertyDisplay dest, MapperContext context)
@@ -59,8 +62,8 @@ namespace Umbraco.Web.Models.Mapping
}
//Translate
dest.Label = _textService.UmbracoDictionaryTranslate(dest.Label);
dest.Description = _textService.UmbracoDictionaryTranslate(dest.Description);
dest.Label = _textService.UmbracoDictionaryTranslate(_cultureDictionary, dest.Label);
dest.Description = _textService.UmbracoDictionaryTranslate(_cultureDictionary, dest.Description);
}
}
}

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Logging;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
@@ -17,11 +18,11 @@ namespace Umbraco.Web.Models.Mapping
private readonly ContentPropertyDtoMapper _contentPropertyDtoConverter;
private readonly ContentPropertyDisplayMapper _contentPropertyDisplayMapper;
public ContentPropertyMapDefinition(IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors)
public ContentPropertyMapDefinition(ICultureDictionary cultureDictionary, IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors)
{
_contentPropertyBasicConverter = new ContentPropertyBasicMapper<ContentPropertyBasic>(dataTypeService, entityService, logger, propertyEditors);
_contentPropertyDtoConverter = new ContentPropertyDtoMapper(dataTypeService, entityService, logger, propertyEditors);
_contentPropertyDisplayMapper = new ContentPropertyDisplayMapper(dataTypeService, entityService, textService, logger, propertyEditors);
_contentPropertyDisplayMapper = new ContentPropertyDisplayMapper(cultureDictionary, dataTypeService, entityService, textService, logger, propertyEditors);
}
public void DefineMaps(UmbracoMapper mapper)

View File

@@ -1,6 +1,7 @@
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
@@ -21,7 +22,7 @@ namespace Umbraco.Web.Models.Mapping
private readonly IMediaTypeService _mediaTypeService;
private readonly TabsAndPropertiesMapper<IMedia> _tabsAndPropertiesMapper;
public MediaMapDefinition(ILogger logger, CommonMapper commonMapper, IMediaService mediaService, IMediaTypeService mediaTypeService,
public MediaMapDefinition(ICultureDictionary cultureDictionary, ILogger logger, CommonMapper commonMapper, IMediaService mediaService, IMediaTypeService mediaTypeService,
ILocalizedTextService localizedTextService)
{
_logger = logger;
@@ -29,7 +30,7 @@ namespace Umbraco.Web.Models.Mapping
_mediaService = mediaService;
_mediaTypeService = mediaTypeService;
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IMedia>(localizedTextService);
_tabsAndPropertiesMapper = new TabsAndPropertiesMapper<IMedia>(cultureDictionary, localizedTextService);
}
public void DefineMaps(UmbracoMapper mapper)

View File

@@ -10,6 +10,7 @@ using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Core.Dictionary;
namespace Umbraco.Web.Models.Mapping
{
@@ -26,15 +27,13 @@ namespace Umbraco.Web.Models.Mapping
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly ILocalizedTextService _localizedTextService;
private readonly IMemberTypeService _memberTypeService;
private readonly IMemberService _memberService;
private readonly IUserService _userService;
public MemberTabsAndPropertiesMapper(IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService, IMemberService memberService, IUserService userService, IMemberTypeService memberTypeService)
: base(localizedTextService)
public MemberTabsAndPropertiesMapper(ICultureDictionary cultureDictionary, IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService, IUserService userService, IMemberTypeService memberTypeService)
: base(cultureDictionary, localizedTextService)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService));
_memberService = memberService ?? throw new ArgumentNullException(nameof(memberService));
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
_memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService));
}
@@ -123,7 +122,7 @@ namespace Umbraco.Web.Models.Mapping
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype",
Label = _localizedTextService.Localize("content/membertype"),
Value = _localizedTextService.UmbracoDictionaryTranslate(member.ContentType.Name),
Value = _localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, member.ContentType.Name),
View = Current.PropertyEditors[Constants.PropertyEditors.Aliases.Label].GetValueEditor().View
},
GetLoginProperty(_memberTypeService, member, _localizedTextService),

View File

@@ -7,22 +7,25 @@ using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Composing;
using Umbraco.Core.Dictionary;
namespace Umbraco.Web.Models.Mapping
{
internal abstract class TabsAndPropertiesMapper
{
protected ICultureDictionary CultureDictionary { get; }
protected ILocalizedTextService LocalizedTextService { get; }
protected IEnumerable<string> IgnoreProperties { get; set; }
protected TabsAndPropertiesMapper(ILocalizedTextService localizedTextService)
protected TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService)
{
CultureDictionary = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary));
LocalizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService));
IgnoreProperties = new List<string>();
}
protected TabsAndPropertiesMapper(ILocalizedTextService localizedTextService, IEnumerable<string> ignoreProperties)
: this(localizedTextService)
protected TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService, IEnumerable<string> ignoreProperties)
: this(cultureDictionary, localizedTextService)
{
IgnoreProperties = ignoreProperties ?? throw new ArgumentNullException(nameof(ignoreProperties));
}
@@ -115,8 +118,8 @@ namespace Umbraco.Web.Models.Mapping
internal class TabsAndPropertiesMapper<TSource> : TabsAndPropertiesMapper
where TSource : IContentBase
{
public TabsAndPropertiesMapper(ILocalizedTextService localizedTextService)
: base(localizedTextService)
public TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService)
: base(cultureDictionary, localizedTextService)
{ }
public virtual IEnumerable<Tab<ContentPropertyDisplay>> Map(TSource source, MapperContext context)
@@ -159,7 +162,7 @@ namespace Umbraco.Web.Models.Mapping
{
Id = groupId,
Alias = groupName,
Label = LocalizedTextService.UmbracoDictionaryTranslate(groupName),
Label = LocalizedTextService.UmbracoDictionaryTranslate(CultureDictionary, groupName),
Properties = mappedProperties,
IsActive = false
});

View File

@@ -1,4 +1,6 @@
using Umbraco.Core.Composing;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Dictionary;
namespace Umbraco.Web.Runtime
{
@@ -7,5 +9,16 @@ namespace Umbraco.Web.Runtime
[ComposeAfter(typeof(IUserComposer))]
[ComposeAfter(typeof(ICoreComposer))]
public class WebFinalComposer : ComponentComposer<WebFinalComponent>
{ }
{
public override void Compose(Composition composition)
{
base.Compose(composition);
// now that user composers have had a chance to register their own factory, we can add the result of the factory
// to the container.
composition.Register(f => f.GetInstance<ICultureDictionaryFactory>().CreateDictionary(), Lifetime.Singleton);
}
}
}

View File

@@ -202,7 +202,7 @@ namespace Umbraco.Web.Runtime
composition.RegisterUnique<ISiteDomainHelper, SiteDomainHelper>();
composition.RegisterUnique<ICultureDictionaryFactory, DefaultCultureDictionaryFactory>();
composition.SetCultureDictionaryFactory<DefaultCultureDictionaryFactory>();
// register *all* checks, except those marked [HideFromTypeFinder] of course
composition.WithCollectionBuilder<HealthCheckCollectionBuilder>()