* Introduced IDataTypeConfigurationCache * Applied IDataTypeConfigurationCache to Property Editors and display mapping * Invalidate new cache trough DataTypeConfigurationCacheRefresher * Improve IDatatype service to use cached int path when fetching by guid (using idkeymap) --------- Co-authored-by: Sven Geusens <sge@umbraco.dk> Co-authored-by: Ronald Barendse <ronald@barend.se>
347 lines
16 KiB
C#
347 lines
16 KiB
C#
// Copyright (c) Umbraco.
|
|
// See LICENSE for more details.
|
|
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Options;
|
|
using Umbraco.Cms.Core.Cache;
|
|
using Umbraco.Cms.Core.Composing;
|
|
using Umbraco.Cms.Core.Configuration;
|
|
using Umbraco.Cms.Core.Configuration.Grid;
|
|
using Umbraco.Cms.Core.Configuration.Models;
|
|
using Umbraco.Cms.Core.Diagnostics;
|
|
using Umbraco.Cms.Core.Dictionary;
|
|
using Umbraco.Cms.Core.Editors;
|
|
using Umbraco.Cms.Core.Events;
|
|
using Umbraco.Cms.Core.Features;
|
|
using Umbraco.Cms.Core.Handlers;
|
|
using Umbraco.Cms.Core.Hosting;
|
|
using Umbraco.Cms.Core.Install;
|
|
using Umbraco.Cms.Core.IO;
|
|
using Umbraco.Cms.Core.Logging;
|
|
using Umbraco.Cms.Core.Mail;
|
|
using Umbraco.Cms.Core.Models.PublishedContent;
|
|
using Umbraco.Cms.Core.Notifications;
|
|
using Umbraco.Cms.Core.Packaging;
|
|
using Umbraco.Cms.Core.Persistence.Repositories;
|
|
using Umbraco.Cms.Core.PropertyEditors;
|
|
using Umbraco.Cms.Core.PublishedCache;
|
|
using Umbraco.Cms.Core.PublishedCache.Internal;
|
|
using Umbraco.Cms.Core.Routing;
|
|
using Umbraco.Cms.Core.Runtime;
|
|
using Umbraco.Cms.Core.Scoping;
|
|
using Umbraco.Cms.Core.Security;
|
|
using Umbraco.Cms.Core.Services;
|
|
using Umbraco.Cms.Core.DynamicRoot;
|
|
using Umbraco.Cms.Core.Sync;
|
|
using Umbraco.Cms.Core.Telemetry;
|
|
using Umbraco.Cms.Core.Templates;
|
|
using Umbraco.Cms.Core.Web;
|
|
using Umbraco.Extensions;
|
|
|
|
namespace Umbraco.Cms.Core.DependencyInjection
|
|
{
|
|
public class UmbracoBuilder : IUmbracoBuilder
|
|
{
|
|
private readonly Dictionary<Type, ICollectionBuilder> _builders = new Dictionary<Type, ICollectionBuilder>();
|
|
|
|
public IServiceCollection Services { get; }
|
|
|
|
public IConfiguration Config { get; }
|
|
|
|
public TypeLoader TypeLoader { get; }
|
|
|
|
/// <inheritdoc />
|
|
public ILoggerFactory BuilderLoggerFactory { get; }
|
|
|
|
/// <inheritdoc />
|
|
public IHostingEnvironment? BuilderHostingEnvironment { get; }
|
|
|
|
public IProfiler Profiler { get; }
|
|
|
|
public AppCaches AppCaches { get; }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="UmbracoBuilder"/> class primarily for testing.
|
|
/// </summary>
|
|
public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader)
|
|
: this(services, config, typeLoader, NullLoggerFactory.Instance, new NoopProfiler(), AppCaches.Disabled, null)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="UmbracoBuilder"/> class.
|
|
/// </summary>
|
|
public UmbracoBuilder(
|
|
IServiceCollection services,
|
|
IConfiguration config,
|
|
TypeLoader typeLoader,
|
|
ILoggerFactory loggerFactory,
|
|
IProfiler profiler,
|
|
AppCaches appCaches,
|
|
IHostingEnvironment? hostingEnvironment)
|
|
{
|
|
Services = services;
|
|
Config = config;
|
|
BuilderLoggerFactory = loggerFactory;
|
|
BuilderHostingEnvironment = hostingEnvironment;
|
|
Profiler = profiler;
|
|
AppCaches = appCaches;
|
|
TypeLoader = typeLoader;
|
|
|
|
AddCoreServices();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a collection builder (and registers the collection).
|
|
/// </summary>
|
|
/// <typeparam name="TBuilder">The type of the collection builder.</typeparam>
|
|
/// <returns>The collection builder.</returns>
|
|
public TBuilder WithCollectionBuilder<TBuilder>()
|
|
where TBuilder : ICollectionBuilder
|
|
{
|
|
Type typeOfBuilder = typeof(TBuilder);
|
|
|
|
if (_builders.TryGetValue(typeOfBuilder, out ICollectionBuilder? o))
|
|
{
|
|
return (TBuilder)o;
|
|
}
|
|
|
|
TBuilder builder;
|
|
if (typeof(TBuilder).GetConstructor(Type.EmptyTypes) != null)
|
|
{
|
|
builder = Activator.CreateInstance<TBuilder>();
|
|
}
|
|
else if (typeof(TBuilder).GetConstructor(new[] { typeof(IUmbracoBuilder) }) != null)
|
|
{
|
|
// Handle those collection builders which need a reference to umbraco builder i.e. DistributedLockingCollectionBuilder.
|
|
builder = (TBuilder)Activator.CreateInstance(typeof(TBuilder), this)!;
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("A CollectionBuilder must have either a parameterless constructor or a constructor whose only parameter is of type IUmbracoBuilder");
|
|
}
|
|
|
|
_builders[typeOfBuilder] = builder;
|
|
return builder;
|
|
}
|
|
|
|
public void Build()
|
|
{
|
|
foreach (ICollectionBuilder builder in _builders.Values)
|
|
{
|
|
builder.RegisterWith(Services);
|
|
}
|
|
|
|
_builders.Clear();
|
|
}
|
|
|
|
private void AddCoreServices()
|
|
{
|
|
Services.AddSingleton(AppCaches);
|
|
Services.AddSingleton(Profiler);
|
|
|
|
// Register as singleton to allow injection everywhere.
|
|
Services.AddSingleton<ServiceFactory>(p => p.GetService!);
|
|
Services.AddSingleton<IEventAggregator, EventAggregator>();
|
|
|
|
Services.AddLazySupport();
|
|
|
|
// Adds no-op registrations as many core services require these dependencies but these
|
|
// dependencies cannot be fulfilled in the Core project
|
|
Services.AddUnique<IMarchal, NoopMarchal>();
|
|
Services.AddUnique<IApplicationShutdownRegistry, NoopApplicationShutdownRegistry>();
|
|
|
|
Services.AddUnique<IMainDom, MainDom>();
|
|
Services.AddUnique<IMainDomLock, MainDomSemaphoreLock>();
|
|
|
|
Services.AddUnique<IIOHelper>(factory =>
|
|
{
|
|
IHostingEnvironment hostingEnvironment = factory.GetRequiredService<IHostingEnvironment>();
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
{
|
|
return new IOHelperLinux(hostingEnvironment);
|
|
}
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
|
{
|
|
return new IOHelperOSX(hostingEnvironment);
|
|
}
|
|
|
|
return new IOHelperWindows(hostingEnvironment);
|
|
});
|
|
|
|
Services.AddUnique(factory => factory.GetRequiredService<AppCaches>().RuntimeCache);
|
|
Services.AddUnique(factory => factory.GetRequiredService<AppCaches>().RequestCache);
|
|
Services.AddUnique<IProfilingLogger, ProfilingLogger>();
|
|
Services.AddUnique<IUmbracoVersion, UmbracoVersion>();
|
|
Services.AddUnique<IEntryAssemblyMetadata, EntryAssemblyMetadata>();
|
|
|
|
this.AddAllCoreCollectionBuilders();
|
|
this.AddNotificationHandler<UmbracoApplicationStartingNotification, EssentialDirectoryCreator>();
|
|
|
|
Services.AddSingleton<UmbracoRequestPaths>();
|
|
|
|
Services.AddSingleton<InstallStatusTracker>();
|
|
|
|
Services.AddUnique<ICultureDictionaryFactory, DefaultCultureDictionaryFactory>();
|
|
Services.AddSingleton(f => f.GetRequiredService<ICultureDictionaryFactory>().CreateDictionary());
|
|
|
|
Services.AddSingleton<UriUtility>();
|
|
|
|
Services.AddUnique<IDashboardService, DashboardService>();
|
|
Services.AddSingleton<IMetricsConsentService, MetricsConsentService>();
|
|
|
|
// will be injected in controllers when needed to invoke rest endpoints on Our
|
|
Services.AddUnique<IInstallationService, InstallationService>();
|
|
Services.AddUnique<IUpgradeService, UpgradeService>();
|
|
|
|
// Grid config is not a real config file as we know them
|
|
Services.AddUnique<IGridConfig, GridConfig>();
|
|
|
|
Services.AddUnique<IPublishedUrlProvider, UrlProvider>();
|
|
Services.AddUnique<ISiteDomainMapper, SiteDomainMapper>();
|
|
|
|
Services.AddSingleton<HtmlLocalLinkParser>();
|
|
Services.AddSingleton<HtmlImageSourceParser>();
|
|
Services.AddSingleton<HtmlUrlParser>();
|
|
|
|
// register properties fallback
|
|
Services.AddUnique<IPublishedValueFallback, PublishedValueFallback>();
|
|
|
|
Services.AddSingleton<UmbracoFeatures>();
|
|
|
|
// register published router
|
|
Services.AddUnique<IPublishedRouter, PublishedRouter>();
|
|
|
|
Services.AddUnique<IEventMessagesFactory, DefaultEventMessagesFactory>();
|
|
Services.AddUnique<IEventMessagesAccessor, HybridEventMessagesAccessor>();
|
|
Services.AddUnique<ITreeService, TreeService>();
|
|
Services.AddUnique<ISectionService, SectionService>();
|
|
|
|
Services.AddUnique<ISmsSender, NotImplementedSmsSender>();
|
|
Services.AddUnique<IEmailSender, NotImplementedEmailSender>();
|
|
|
|
Services.AddUnique<IDataValueEditorFactory, DataValueEditorFactory>();
|
|
|
|
// register distributed cache
|
|
Services.AddUnique(f => new DistributedCache(f.GetRequiredService<IServerMessenger>(), f.GetRequiredService<CacheRefresherCollection>()));
|
|
Services.AddUnique<ICacheRefresherNotificationFactory, CacheRefresherNotificationFactory>();
|
|
|
|
// register the http context and umbraco context accessors
|
|
// we *should* use the HttpContextUmbracoContextAccessor, however there are cases when
|
|
// we have no http context, eg when booting Umbraco or in background threads, so instead
|
|
// let's use an hybrid accessor that can fall back to a ThreadStatic context.
|
|
Services.AddUnique<IUmbracoContextAccessor, HybridUmbracoContextAccessor>();
|
|
|
|
Services.AddSingleton<LegacyPasswordSecurity>();
|
|
Services.AddSingleton<UserEditorAuthorizationHelper>();
|
|
Services.AddSingleton<ContentPermissions>();
|
|
Services.AddSingleton<MediaPermissions>();
|
|
|
|
Services.AddSingleton<PropertyEditorCollection>();
|
|
Services.AddSingleton<ParameterEditorCollection>();
|
|
|
|
// register a server registrar, by default it's the db registrar
|
|
Services.AddUnique<IServerRoleAccessor>(f =>
|
|
{
|
|
GlobalSettings globalSettings = f.GetRequiredService<IOptions<GlobalSettings>>().Value;
|
|
var singleServer = globalSettings.DisableElectionForSingleServer;
|
|
return singleServer
|
|
? new SingleServerRoleAccessor()
|
|
: new ElectedServerRoleAccessor(f.GetRequiredService<IServerRegistrationService>());
|
|
});
|
|
|
|
// For Umbraco to work it must have the default IPublishedModelFactory
|
|
// which may be replaced by models builder but the default is required to make plain old IPublishedContent
|
|
// instances.
|
|
Services.AddSingleton<IPublishedModelFactory>(factory => factory.CreateDefaultPublishedModelFactory());
|
|
|
|
Services
|
|
.AddNotificationHandler<MemberGroupSavedNotification, PublicAccessHandler>()
|
|
.AddNotificationHandler<MemberGroupDeletedNotification, PublicAccessHandler>();
|
|
|
|
Services.AddSingleton<ISyncBootStateAccessor, NonRuntimeLevelBootStateAccessor>();
|
|
|
|
// register a basic/noop published snapshot service to be replaced
|
|
Services.AddSingleton<IPublishedSnapshotService, InternalPublishedSnapshotService>();
|
|
|
|
// Register ValueEditorCache used for validation
|
|
Services.AddSingleton<IValueEditorCache, ValueEditorCache>();
|
|
|
|
// Register telemetry service used to gather data about installed packages
|
|
Services.AddUnique<ISiteIdentifierService, SiteIdentifierService>();
|
|
Services.AddUnique<ITelemetryService, TelemetryService>();
|
|
|
|
Services.AddUnique<IKeyValueService, KeyValueService>();
|
|
Services.AddUnique<IPublicAccessService, PublicAccessService>();
|
|
Services.AddUnique<IContentVersionService, ContentVersionService>();
|
|
Services.AddUnique<IUserService, UserService>();
|
|
Services.AddUnique<ILocalizationService, LocalizationService>();
|
|
Services.AddUnique<IMacroService, MacroService>();
|
|
Services.AddUnique<IMemberGroupService, MemberGroupService>();
|
|
Services.AddUnique<IRedirectUrlService, RedirectUrlService>();
|
|
Services.AddUnique<IConsentService, ConsentService>();
|
|
Services.AddUnique<IPropertyValidationService, PropertyValidationService>();
|
|
Services.AddUnique<IDomainService, DomainService>();
|
|
Services.AddUnique<ITagService, TagService>();
|
|
Services.AddUnique<IContentService, ContentService>();
|
|
Services.AddUnique<IContentVersionCleanupPolicy, DefaultContentVersionCleanupPolicy>();
|
|
Services.AddUnique<IMemberService, MemberService>();
|
|
Services.AddUnique<IMediaService, MediaService>();
|
|
Services.AddUnique<IContentTypeService, ContentTypeService>();
|
|
Services.AddUnique<IContentTypeBaseServiceProvider, ContentTypeBaseServiceProvider>();
|
|
Services.AddUnique<IMediaTypeService, MediaTypeService>();
|
|
Services.AddUnique<IFileService, FileService>();
|
|
Services.AddUnique<IEntityService, EntityService>();
|
|
Services.AddUnique<IRelationService, RelationService>();
|
|
Services.AddUnique<IMemberTypeService, MemberTypeService>();
|
|
Services.AddUnique<INotificationService, NotificationService>();
|
|
Services.AddUnique<ITrackedReferencesService, TrackedReferencesService>();
|
|
Services.AddUnique<ExternalLoginService>(factory => new ExternalLoginService(
|
|
factory.GetRequiredService<ICoreScopeProvider>(),
|
|
factory.GetRequiredService<ILoggerFactory>(),
|
|
factory.GetRequiredService<IEventMessagesFactory>(),
|
|
factory.GetRequiredService<IExternalLoginWithKeyRepository>()
|
|
));
|
|
Services.AddUnique<IExternalLoginWithKeyService>(factory => factory.GetRequiredService<ExternalLoginService>());
|
|
Services.AddUnique<ILocalizedTextService>(factory => new LocalizedTextService(
|
|
factory.GetRequiredService<Lazy<LocalizedTextServiceFileSources>>(),
|
|
factory.GetRequiredService<ILogger<LocalizedTextService>>()));
|
|
|
|
Services.AddUnique<IEntityXmlSerializer, EntityXmlSerializer>();
|
|
|
|
Services.AddSingleton<ConflictingPackageData>();
|
|
Services.AddSingleton<CompiledPackageXmlParser>();
|
|
|
|
// Register a noop IHtmlSanitizer & IMarkdownSanitizer to be replaced
|
|
Services.AddUnique<IHtmlSanitizer, NoopHtmlSanitizer>();
|
|
Services.AddUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>();
|
|
|
|
Services.AddUnique<IPropertyTypeUsageService, PropertyTypeUsageService>();
|
|
Services.AddUnique<IDataTypeUsageService, DataTypeUsageService>();
|
|
|
|
Services.AddUnique<ICultureImpactFactory>(provider => new CultureImpactFactory(provider.GetRequiredService<IOptionsMonitor<ContentSettings>>()));
|
|
Services.AddUnique<IDictionaryService, DictionaryService>();
|
|
Services.AddUnique<ITemporaryMediaService, TemporaryMediaService>();
|
|
|
|
// Register filestream security analyzers
|
|
Services.AddUnique<IFileStreamSecurityValidator,FileStreamSecurityValidator>();
|
|
Services.AddUnique<IDynamicRootService,DynamicRoot.DynamicRootService>();
|
|
|
|
// Register Webhook services
|
|
Services.AddUnique<IWebhookService, WebhookService>();
|
|
Services.AddUnique<IWebhookLogService, WebhookLogService>();
|
|
Services.AddUnique<IWebhookLogFactory, WebhookLogFactory>();
|
|
Services.AddUnique<IWebhookRequestService, WebhookRequestService>();
|
|
|
|
// Data type configuration cache
|
|
Services.AddUnique<IDataTypeConfigurationCache, DataTypeConfigurationCache>();
|
|
Services.AddNotificationHandler<DataTypeCacheRefresherNotification, DataTypeConfigurationCacheRefresher>();
|
|
}
|
|
}
|
|
}
|