Files
Umbraco-CMS/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs

376 lines
18 KiB
C#
Raw Normal View History

2019-01-03 21:00:28 +01:00
using System;
using Examine;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.CompositionExtensions;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Configuration;
2020-03-13 20:37:10 +01:00
using Umbraco.Core.Configuration.Grid;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Dashboards;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
2020-04-20 12:20:47 +02:00
using Umbraco.Core.Install;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.Media;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Migrations;
using Umbraco.Core.Migrations.Install;
2019-02-13 09:53:17 +01:00
using Umbraco.Core.Migrations.PostMigrations;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.Validators;
using Umbraco.Core.PropertyEditors.ValueConverters;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Scoping;
using Umbraco.Core.Serialization;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
2019-01-03 21:00:28 +01:00
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Core.Templates;
using Umbraco.Examine;
using Umbraco.Infrastructure.Examine;
using Umbraco.Infrastructure.Media;
using Umbraco.Web;
using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Editors;
using Umbraco.Web.Features;
using Umbraco.Web.HealthCheck;
using Umbraco.Web.HealthCheck.NotificationMethods;
using Umbraco.Web.Install;
using Umbraco.Web.Media;
using Umbraco.Web.Media.EmbedProviders;
using Umbraco.Web.Migrations.PostMigrations;
using Umbraco.Web.Models.PublishedContent;
using Umbraco.Web.PropertyEditors;
2020-08-06 12:59:21 +02:00
using Umbraco.Web.PropertyEditors.ValueConverters;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Search;
using Umbraco.Web.Sections;
using Umbraco.Web.Services;
using Umbraco.Web.Templates;
using Umbraco.Web.Trees;
2019-01-03 21:00:28 +01:00
using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator;
2020-08-06 12:59:21 +02:00
using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter;
2020-09-28 08:26:21 +02:00
using Microsoft.Extensions.Logging;
Netcore/feature/healthcheck replaceconfiglogic (#8934) * Started moving to JSON instead of config. Mild refactoring but overall keeping it the same, except for injecting IConfiguration and JSON parsing instead of XML Tests currently unaffected, need to increase coverage * Moved to constants for appsettings keys Moved from IConfiguration to global settings - later to be replaced with IOptions Updated translation messages Installed IOptions ready for new PR Updated to new interface, IConfigurationService * Post-merge fix * Namespace move from Umbraco.Web to Umbraco.Core where appropriate * Renamed abstractsettings (from abstractconfig) Moving out of configservice into the POCO config check * Made the IIsCustomErrors healthcheck as obsolete, as no web.config setting). Investigate reintroducing this check in the .NET Core way (UseDevelopment). Reducing use of abstractsettings as not needed - we don't need a config service to read the config settings anymore as they're all explicit POCOs. Consolidated health-checks in project. * Removed test views that weren't meant to be added * Returned to use of abstractsettings with different use * Moved more health checks into correct folder/namespace, and enum into their own file * Correct namespace * Git history/compare lost due to file move, temporarily moving back to original folder. Will do another PR to move after this * Use existing GetStatus in abstract check for Debug mode * Updating to return to previous logic and putting files back into line * Macro errors returned to previous logic * Reuse abstractsettings class * Swapped order to assist with reviewing PR * Updated to include itempath * Not implemented comment to avoid confusion Implemented NotificationEmailCheck * Changed to IOptionsMonitor as per PR comments. Removed configurationservice as we need to rethink the fixing strategy. Updated logger. Needs to show fix message instead of fixing. Temporary fix for IIS version * Switched to IOptionsMonitor for all * No longer attempts to actually fix header in config. Still need to show suggestions. Co-authored-by: Elitsa Marinovska <elm@umbraco.dk>
2020-10-21 10:29:25 +01:00
using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Core.HealthCheck;
using Umbraco.Core.HealthCheck.Checks;
2019-01-03 21:00:28 +01:00
namespace Umbraco.Core.Runtime
{
2019-03-05 08:47:31 +01:00
// core's initial composer composes before all core composers
[ComposeBefore(typeof(ICoreComposer))]
public class CoreInitialComposer : ComponentComposer<CoreInitialComponent>
2019-01-03 21:00:28 +01:00
{
public override void Compose(Composition composition)
2019-01-03 21:00:28 +01:00
{
base.Compose(composition);
2019-01-03 21:00:28 +01:00
// composers
composition
.ComposeRepositories()
.ComposeServices()
.ComposeCoreMappingProfiles()
.ComposeFileSystems();
// register persistence mappers - required by database factory so needs to be done here
// means the only place the collection can be modified is in a runtime - afterwards it
// has been frozen and it is too late
composition.Mappers().AddCoreMappers();
2019-01-03 21:00:28 +01:00
// register the scope provider
composition.Services.AddUnique<ScopeProvider>(); // implements both IScopeProvider and IScopeAccessor
composition.Services.AddUnique<IScopeProvider>(f => f.GetRequiredService<ScopeProvider>());
composition.Services.AddUnique<IScopeAccessor>(f => f.GetRequiredService<ScopeProvider>());
2019-01-03 21:00:28 +01:00
composition.Services.AddUnique<IJsonSerializer, JsonNetSerializer>();
composition.Services.AddUnique<IMenuItemCollectionFactory, MenuItemCollectionFactory>();
composition.Services.AddUnique<InstallStatusTracker>();
2019-01-03 21:00:28 +01:00
// register database builder
// *not* a singleton, don't want to keep it around
composition.Services.AddTransient<DatabaseBuilder>();
2019-01-03 21:00:28 +01:00
// register manifest parser, will be injected in collection builders where needed
composition.Services.AddUnique<IManifestParser, ManifestParser>();
2019-01-03 21:00:28 +01:00
// register our predefined validators
composition.ManifestValueValidators()
2019-01-03 21:00:28 +01:00
.Add<RequiredValidator>()
.Add<RegexValidator>()
.Add<DelimitedValueValidator>()
.Add<EmailValidator>()
.Add<IntegerValidator>()
.Add<DecimalValidator>();
// register the manifest filter collection builder (collection is empty by default)
composition.ManifestFilters();
2019-01-03 21:00:28 +01:00
// properties and parameters derive from data editors
composition.DataEditors()
2019-01-03 21:00:28 +01:00
.Add(() => composition.TypeLoader.GetDataEditors());
composition.MediaUrlGenerators()
.Add<FileUploadPropertyEditor>()
.Add<ImageCropperPropertyEditor>();
composition.Services.AddUnique<PropertyEditorCollection>();
composition.Services.AddUnique<ParameterEditorCollection>();
2019-01-03 21:00:28 +01:00
// Used to determine if a datatype/editor should be storing/tracking
// references to media item/s
composition.DataValueReferenceFactories();
2019-01-03 21:00:28 +01:00
// register a server registrar, by default it's the db registrar
composition.Services.AddUnique<IServerRegistrar>(f =>
2019-01-03 21:00:28 +01:00
{
var globalSettings = f.GetRequiredService<IOptions<GlobalSettings>>().Value;
// TODO: we still register the full IServerMessenger because
// even on 1 single server we can have 2 concurrent app domains
var singleServer = globalSettings.DisableElectionForSingleServer;
return singleServer
? (IServerRegistrar) new SingleServerRegistrar(f.GetRequiredService<IRequestAccessor>())
: new DatabaseServerRegistrar(
new Lazy<IServerRegistrationService>(f.GetRequiredService<IServerRegistrationService>),
new DatabaseServerRegistrarOptions());
2019-01-03 21:00:28 +01:00
});
// by default we'll use the database server messenger with default options (no callbacks),
// this will be overridden by the db thing in the corresponding components in the web
// project
composition.Services.AddUnique<IServerMessenger>(factory
2019-01-03 21:00:28 +01:00
=> new DatabaseServerMessenger(
factory.GetRequiredService<IMainDom>(),
factory.GetRequiredService<IScopeProvider>(),
factory.GetRequiredService<ISqlContext>(),
factory.GetRequiredService<IProfilingLogger>(),
factory.GetRequiredService<ILogger<DatabaseServerMessenger>>(),
factory.GetRequiredService<IServerRegistrar>(),
2019-11-19 08:52:39 +01:00
true, new DatabaseServerMessengerOptions(),
factory.GetRequiredService<IHostingEnvironment>(),
factory.GetRequiredService<CacheRefresherCollection>()
));
2019-01-03 21:00:28 +01:00
composition.CacheRefreshers()
2019-01-03 21:00:28 +01:00
.Add(() => composition.TypeLoader.GetCacheRefreshers());
composition.PackageActions()
2019-01-03 21:00:28 +01:00
.Add(() => composition.TypeLoader.GetPackageActions());
composition.PropertyValueConverters()
2019-01-03 21:00:28 +01:00
.Append(composition.TypeLoader.GetTypes<IPropertyValueConverter>());
composition.Services.AddUnique<IPublishedContentTypeFactory, PublishedContentTypeFactory>();
2019-01-03 21:00:28 +01:00
composition.Services.AddUnique<IShortStringHelper>(factory
=> new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService<IOptions<RequestHandlerSettings>>().Value)));
2019-01-03 21:00:28 +01:00
composition.UrlSegmentProviders()
2019-01-03 21:00:28 +01:00
.Append<DefaultUrlSegmentProvider>();
composition.Services.AddUnique<IMigrationBuilder>(factory => new MigrationBuilder(factory));
2019-01-03 21:00:28 +01:00
// by default, register a noop factory
composition.Services.AddUnique<IPublishedModelFactory, NoopPublishedModelFactory>();
2019-02-13 09:53:17 +01:00
// by default
composition.Services.AddUnique<IPublishedSnapshotRebuilder, PublishedSnapshotRebuilder>();
composition.SetCultureDictionaryFactory<DefaultCultureDictionaryFactory>();
composition.Services.AddSingleton(f => f.GetRequiredService<ICultureDictionaryFactory>().CreateDictionary());
composition.Services.AddUnique<UriUtility>();
// register the published snapshot accessor - the "current" published snapshot is in the umbraco context
composition.Services.AddUnique<IPublishedSnapshotAccessor, UmbracoContextPublishedSnapshotAccessor>();
composition.Services.AddUnique<IVariationContextAccessor, HybridVariationContextAccessor>();
composition.Services.AddUnique<IDashboardService, DashboardService>();
// register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards
composition.Dashboards()
.Add(composition.TypeLoader.GetTypes<IDashboard>());
// will be injected in controllers when needed to invoke rest endpoints on Our
composition.Services.AddUnique<IInstallationService, InstallationService>();
composition.Services.AddUnique<IUpgradeService, UpgradeService>();
2020-03-13 20:37:10 +01:00
// Grid config is not a real config file as we know them
composition.Services.AddUnique<IGridConfig, GridConfig>();
// Config manipulator
composition.Services.AddUnique<IConfigManipulator, JsonConfigManipulator>();
Netcore/feature/healthcheck replaceconfiglogic (#8934) * Started moving to JSON instead of config. Mild refactoring but overall keeping it the same, except for injecting IConfiguration and JSON parsing instead of XML Tests currently unaffected, need to increase coverage * Moved to constants for appsettings keys Moved from IConfiguration to global settings - later to be replaced with IOptions Updated translation messages Installed IOptions ready for new PR Updated to new interface, IConfigurationService * Post-merge fix * Namespace move from Umbraco.Web to Umbraco.Core where appropriate * Renamed abstractsettings (from abstractconfig) Moving out of configservice into the POCO config check * Made the IIsCustomErrors healthcheck as obsolete, as no web.config setting). Investigate reintroducing this check in the .NET Core way (UseDevelopment). Reducing use of abstractsettings as not needed - we don't need a config service to read the config settings anymore as they're all explicit POCOs. Consolidated health-checks in project. * Removed test views that weren't meant to be added * Returned to use of abstractsettings with different use * Moved more health checks into correct folder/namespace, and enum into their own file * Correct namespace * Git history/compare lost due to file move, temporarily moving back to original folder. Will do another PR to move after this * Use existing GetStatus in abstract check for Debug mode * Updating to return to previous logic and putting files back into line * Macro errors returned to previous logic * Reuse abstractsettings class * Swapped order to assist with reviewing PR * Updated to include itempath * Not implemented comment to avoid confusion Implemented NotificationEmailCheck * Changed to IOptionsMonitor as per PR comments. Removed configurationservice as we need to rethink the fixing strategy. Updated logger. Needs to show fix message instead of fixing. Temporary fix for IIS version * Switched to IOptionsMonitor for all * No longer attempts to actually fix header in config. Still need to show suggestions. Co-authored-by: Elitsa Marinovska <elm@umbraco.dk>
2020-10-21 10:29:25 +01:00
// register the umbraco context factory
// composition.Services.AddUnique<IUmbracoContextFactory, UmbracoContextFactory>();
composition.Services.AddUnique<IPublishedUrlProvider, UrlProvider>();
composition.Services.AddUnique<HtmlLocalLinkParser>();
composition.Services.AddUnique<HtmlImageSourceParser>();
composition.Services.AddUnique<HtmlUrlParser>();
composition.Services.AddUnique<RichTextEditorPastedImages>();
composition.Services.AddUnique<BlockEditorConverter>();
// both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be
// discovered when CoreBootManager configures the converters. We HAVE to remove one of them
// here because there cannot be two converters for one property editor - and we want the full
// RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter.
// (the limited one, defined in Core, is there for tests) - same for others
composition.PropertyValueConverters()
.Remove<TinyMceValueConverter>()
.Remove<TextStringValueConverter>()
.Remove<MarkdownEditorValueConverter>();
composition.UrlProviders()
.Append<AliasUrlProvider>()
.Append<DefaultUrlProvider>();
composition.MediaUrlProviders()
.Append<DefaultMediaUrlProvider>();
composition.Services.AddUnique<ISiteDomainHelper, SiteDomainHelper>();
// register properties fallback
composition.Services.AddUnique<IPublishedValueFallback, PublishedValueFallback>();
composition.Services.AddUnique<IImageUrlGenerator, ImageSharpImageUrlGenerator>();
composition.Services.AddUnique<UmbracoFeatures>();
composition.Actions()
.Add(() => composition.TypeLoader.GetTypes<IAction>());
composition.EditorValidators()
.Add(() => composition.TypeLoader.GetTypes<IEditorValidator>());
composition.TourFilters();
// replace with web implementation
composition.Services.AddUnique<IPublishedSnapshotRebuilder, PublishedSnapshotRebuilder>();
// register OEmbed providers - no type scanning - all explicit opt-in of adding types
// note: IEmbedProvider is not IDiscoverable - think about it if going for type scanning
composition.OEmbedProviders()
.Append<YouTube>()
.Append<Instagram>()
.Append<Twitter>()
.Append<Vimeo>()
.Append<DailyMotion>()
.Append<Flickr>()
.Append<Slideshare>()
.Append<Kickstarter>()
.Append<GettyImages>()
.Append<Ted>()
.Append<Soundcloud>()
.Append<Issuu>()
.Append<Hulu>()
.Append<Giphy>();
// register back office sections in the order we want them rendered
composition.Sections()
.Append<ContentSection>()
.Append<MediaSection>()
.Append<SettingsSection>()
.Append<PackagesSection>()
.Append<UsersSection>()
.Append<MembersSection>()
.Append<FormsSection>()
.Append<TranslationSection>();
// register known content apps
composition.ContentApps()
.Append<ListViewContentAppFactory>()
.Append<ContentEditorContentAppFactory>()
.Append<ContentInfoContentAppFactory>()
.Append<ContentTypeDesignContentAppFactory>()
.Append<ContentTypeListViewContentAppFactory>()
.Append<ContentTypePermissionsContentAppFactory>()
.Append<ContentTypeTemplatesContentAppFactory>();
// register published router
composition.Services.AddUnique<IPublishedRouter, PublishedRouter>();
// register *all* checks, except those marked [HideFromTypeFinder] of course
composition.HealthChecks()
Netcore/feature/healthcheck replaceconfiglogic (#8934) * Started moving to JSON instead of config. Mild refactoring but overall keeping it the same, except for injecting IConfiguration and JSON parsing instead of XML Tests currently unaffected, need to increase coverage * Moved to constants for appsettings keys Moved from IConfiguration to global settings - later to be replaced with IOptions Updated translation messages Installed IOptions ready for new PR Updated to new interface, IConfigurationService * Post-merge fix * Namespace move from Umbraco.Web to Umbraco.Core where appropriate * Renamed abstractsettings (from abstractconfig) Moving out of configservice into the POCO config check * Made the IIsCustomErrors healthcheck as obsolete, as no web.config setting). Investigate reintroducing this check in the .NET Core way (UseDevelopment). Reducing use of abstractsettings as not needed - we don't need a config service to read the config settings anymore as they're all explicit POCOs. Consolidated health-checks in project. * Removed test views that weren't meant to be added * Returned to use of abstractsettings with different use * Moved more health checks into correct folder/namespace, and enum into their own file * Correct namespace * Git history/compare lost due to file move, temporarily moving back to original folder. Will do another PR to move after this * Use existing GetStatus in abstract check for Debug mode * Updating to return to previous logic and putting files back into line * Macro errors returned to previous logic * Reuse abstractsettings class * Swapped order to assist with reviewing PR * Updated to include itempath * Not implemented comment to avoid confusion Implemented NotificationEmailCheck * Changed to IOptionsMonitor as per PR comments. Removed configurationservice as we need to rethink the fixing strategy. Updated logger. Needs to show fix message instead of fixing. Temporary fix for IIS version * Switched to IOptionsMonitor for all * No longer attempts to actually fix header in config. Still need to show suggestions. Co-authored-by: Elitsa Marinovska <elm@umbraco.dk>
2020-10-21 10:29:25 +01:00
.Add(() => composition.TypeLoader.GetTypes<HealthCheck.HealthCheck>());
composition.WithCollectionBuilder<HealthCheckNotificationMethodCollectionBuilder>()
.Add(() => composition.TypeLoader.GetTypes<IHealthCheckNotificationMethod>());
composition.Services.AddUnique<IContentLastChanceFinder, ContentFinderByConfigured404>();
composition.ContentFinders()
// all built-in finders in the correct order,
// devs can then modify this list on application startup
.Append<ContentFinderByPageIdQuery>()
.Append<ContentFinderByUrl>()
.Append<ContentFinderByIdPath>()
//.Append<ContentFinderByUrlAndTemplate>() // disabled, this is an odd finder
.Append<ContentFinderByUrlAlias>()
.Append<ContentFinderByRedirectUrl>();
composition.Services.AddScoped<UmbracoTreeSearcher>();
composition.SearchableTrees()
.Add(() => composition.TypeLoader.GetTypes<ISearchableTree>());
// replace some services
composition.Services.AddUnique<IEventMessagesFactory, DefaultEventMessagesFactory>();
composition.Services.AddUnique<IEventMessagesAccessor, HybridEventMessagesAccessor>();
composition.Services.AddUnique<ITreeService, TreeService>();
composition.Services.AddUnique<ISectionService, SectionService>();
composition.Services.AddUnique<IEmailSender, EmailSender>();
composition.Services.AddUnique<IExamineManager, ExamineManager>();
// register distributed cache
composition.Services.AddUnique(f => new DistributedCache(f.GetRequiredService<IServerMessenger>(), f.GetRequiredService<CacheRefresherCollection>()));
composition.Services.AddScoped<ITagQuery, TagQuery>();
composition.Services.AddUnique<HtmlLocalLinkParser>();
composition.Services.AddUnique<HtmlUrlParser>();
composition.Services.AddUnique<HtmlImageSourceParser>();
composition.Services.AddUnique<RichTextEditorPastedImages>();
composition.Services.AddUnique<IUmbracoTreeSearcherFields, UmbracoTreeSearcherFields>();
composition.Services.AddScoped<IPublishedContentQuery>(factory =>
{
var umbCtx = factory.GetRequiredService<IUmbracoContextAccessor>();
return new PublishedContentQuery(umbCtx.UmbracoContext.PublishedSnapshot, factory.GetRequiredService<IVariationContextAccessor>(), factory.GetRequiredService<IExamineManager>());
});
composition.Services.AddUnique<IPublishedUrlProvider, UrlProvider>();
// 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.
composition.Services.AddUnique<IUmbracoContextAccessor, HybridUmbracoContextAccessor>();
// register accessors for cultures
composition.Services.AddUnique<IDefaultCultureAccessor, DefaultCultureAccessor>();
composition.Services.AddSingleton<IFilePermissionHelper, FilePermissionHelper>();
composition.Services.AddUnique<IUmbracoComponentRenderer, UmbracoComponentRenderer>();
// Register noop versions for examine to be overridden by examine
composition.Services.AddUnique<IUmbracoIndexesCreator, NoopUmbracoIndexesCreator>();
composition.Services.AddUnique<IBackOfficeExamineSearcher, NoopBackOfficeExamineSearcher>();
composition.Services.AddUnique<UploadAutoFillProperties>();
2019-01-03 21:00:28 +01:00
}
}
}