diff --git a/.gitattributes b/.gitattributes
index c8987ade67..3241b6511c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -43,6 +43,7 @@
*.hs text=auto
*.json text=auto
*.xml text=auto
+*.resx text=auto
*.csproj text=auto merge=union
*.vbproj text=auto merge=union
diff --git a/.gitignore b/.gitignore
index 022acb5db7..ea2ddfbb68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -191,6 +191,7 @@ src/Umbraco.Web.UI/Umbraco/telemetrics-id.umb
/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/*
/src/Umbraco.Web.UI.NetCore/umbraco/logs
+src/Umbraco.Tests.Integration/umbraco/Data/
src/Umbraco.Tests.Integration/umbraco/logs/
src/Umbraco.Tests.Integration/Views/
diff --git a/NuGet.Config b/NuGet.Config
index d6c63173f8..92eaf83792 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -1,13 +1,15 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec
index a88f260431..bf2ca3c5a2 100644
--- a/build/NuSpecs/UmbracoCms.Core.nuspec
+++ b/build/NuSpecs/UmbracoCms.Core.nuspec
@@ -62,6 +62,7 @@
+
diff --git a/build/azure-pipelines.yml b/build/azure-pipelines.yml
index 8a99f941b0..92c2cb13ed 100644
--- a/build/azure-pipelines.yml
+++ b/build/azure-pipelines.yml
@@ -8,6 +8,19 @@
# Variables & their default values
variables:
buildConfiguration: 'Release'
+ SA_PASSWORD: UmbracoIntegration123!
+
+resources:
+ containers:
+ - container: mssql
+ image: mcr.microsoft.com/mssql/server:2017-latest
+ env:
+ ACCEPT_EULA: Y
+ SA_PASSWORD: $(SA_PASSWORD)
+ MSSQL_PID: Developer
+ ports:
+ - 1433:1433
+ options: --name mssql
stages:
- stage: Linux
@@ -31,27 +44,48 @@ stages:
command: test
projects: '**/*.Tests.UnitTests.csproj'
-- stage: macOS_X
+ - job: Integration_Tests
+ services:
+ mssql: mssql
+ timeoutInMinutes: 120
+ displayName: 'Integration Tests'
+ pool:
+ vmImage: 'ubuntu-latest'
+ steps:
+
+ - task: UseDotNet@2
+ displayName: 'Use .Net Core sdk 3.1.x'
+ inputs:
+ version: 3.1.x
+
+ - task: DotNetCoreCLI@2
+ displayName: 'dotnet test'
+ inputs:
+ command: test
+ projects: '**/Umbraco.Tests.Integration.csproj'
+ env:
+ UmbracoIntegrationTestConnectionString: 'Server=localhost,1433;User Id=sa;Password=$(SA_PASSWORD);'
+
+- stage: MacOS
dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel
jobs:
- - job: Unit_Tests
- displayName: 'Unit Tests'
- pool:
- vmImage: 'macOS-latest'
- steps:
+ - job: Unit_Tests
+ displayName: 'Unit Tests'
+ pool:
+ vmImage: 'macOS-latest'
+ steps:
- - task: UseDotNet@2
- displayName: 'Use .Net Core sdk 3.1.x'
- inputs:
- version: 3.1.x
-
- - task: DotNetCoreCLI@2
- displayName: 'dotnet test'
- inputs:
- command: test
- projects: '**/*.Tests.UnitTests.csproj'
+ - task: UseDotNet@2
+ displayName: 'Use .Net Core sdk 3.1.x'
+ inputs:
+ version: 3.1.x
+ - task: DotNetCoreCLI@2
+ displayName: 'dotnet test'
+ inputs:
+ command: test
+ projects: '**/*.Tests.UnitTests.csproj'
- stage: Windows
dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel
@@ -74,7 +108,6 @@ stages:
command: test
projects: '**\*.Tests.UnitTests.csproj'
-
- job: Integration_Tests
timeoutInMinutes: 120
displayName: 'Integration Tests'
@@ -87,11 +120,6 @@ stages:
inputs:
version: 3.1.x
- - task: DotNetCoreCLI@2
- displayName: 'dotnet build'
- inputs:
- projects: '**\Umbraco.Tests.Integration.csproj'
-
- powershell: 'sqllocaldb start mssqllocaldb'
displayName: 'Start MSSQL LocalDb'
@@ -100,8 +128,6 @@ stages:
inputs:
command: test
projects: '**\Umbraco.Tests.Integration.csproj'
- arguments: '--no-build'
-
- job: Build_Artifacts
displayName: 'Build Artifacts'
@@ -144,6 +170,13 @@ stages:
$continuous = "$($version.Release)-alpha.$(Build.BuildNumber)"
}
$ubuild.SetUmbracoVersion($continuous)
+
+ #Update the version in template also
+ $templatePath = 'build/templates/UmbracoSolution/.template.config/template.json'
+ $a = Get-Content $templatePath -raw | ConvertFrom-Json
+ $a.symbols.version.defaultValue = $continuous
+ $a | ConvertTo-Json -depth 32| set-content $templatePath
+
Write-Host "Building: $continuous"
- task: PowerShell@1
diff --git a/build/templates/UmbracoSolution/.template.config/template.json b/build/templates/UmbracoSolution/.template.config/template.json
index 04f77a556e..6dc582ca26 100644
--- a/build/templates/UmbracoSolution/.template.config/template.json
+++ b/build/templates/UmbracoSolution/.template.config/template.json
@@ -9,7 +9,7 @@
"language": "C#",
"type": "project"
},
- "sourceName": "UmbracoSolution", // Will be replaced with the value provided via -n
+ "sourceName": "UmbracoSolution",
"preferNameDirectory": true,
"symbols": {
"version": {
diff --git a/src/Umbraco.Core/Cache/DistributedCache.cs b/src/Umbraco.Core/Cache/DistributedCache.cs
index 698e97c610..7ad9f9569f 100644
--- a/src/Umbraco.Core/Cache/DistributedCache.cs
+++ b/src/Umbraco.Core/Cache/DistributedCache.cs
@@ -46,7 +46,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || instances.Length == 0 || getNumericId == null) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
getNumericId,
instances);
@@ -61,7 +61,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || id == default(int)) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
id);
}
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || id == Guid.Empty) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
id);
}
@@ -86,7 +86,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || payload == null) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
payload);
}
@@ -97,7 +97,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || payloads == null) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
payloads.ToArray());
}
@@ -125,7 +125,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty) return;
- _serverMessenger.PerformRefreshAll(
+ _serverMessenger.QueueRefreshAll(
GetRefresherById(refresherGuid));
}
@@ -138,7 +138,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || id == default(int)) return;
- _serverMessenger.PerformRemove(
+ _serverMessenger.QueueRemove(
GetRefresherById(refresherGuid),
id);
}
@@ -155,7 +155,7 @@ namespace Umbraco.Web.Cache
///
public void Remove(Guid refresherGuid, Func getNumericId, params T[] instances)
{
- _serverMessenger.PerformRemove(
+ _serverMessenger.QueueRemove(
GetRefresherById(refresherGuid),
getNumericId,
instances);
@@ -164,9 +164,15 @@ namespace Umbraco.Web.Cache
#endregion
// helper method to get an ICacheRefresher by its unique identifier
- private ICacheRefresher GetRefresherById(Guid refresherGuid)
+ private ICacheRefresher GetRefresherById(Guid refresherGuid)
{
- return _cacheRefreshers[refresherGuid];
+ ICacheRefresher refresher = _cacheRefreshers[refresherGuid];
+ if (refresher == null)
+ {
+ throw new InvalidOperationException($"No cache refresher found with id {refresherGuid}");
+ }
+
+ return refresher;
}
}
}
diff --git a/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs b/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs
deleted file mode 100644
index 31e876892e..0000000000
--- a/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Umbraco.Core.Composing;
-
-namespace Umbraco.Web.Cache
-{
- public class DistributedCacheBinderComponent : IComponent
- {
- private readonly IDistributedCacheBinder _binder;
-
- public DistributedCacheBinderComponent(IDistributedCacheBinder distributedCacheBinder)
- {
- _binder = distributedCacheBinder;
- }
-
- public void Initialize()
- {
- _binder.BindEvents();
- }
-
- public void Terminate()
- { }
- }
-}
diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs
index 1c4de6cd8e..14089ba924 100644
--- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs
+++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.Composing
{
diff --git a/src/Umbraco.Core/Composing/Composers.cs b/src/Umbraco.Core/Composing/Composers.cs
index 47f272cbf4..91c8244324 100644
--- a/src/Umbraco.Core/Composing/Composers.cs
+++ b/src/Umbraco.Core/Composing/Composers.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -70,7 +70,6 @@ namespace Umbraco.Core.Composing
foreach (var composer in composers)
{
- var componentType = composer.GetType();
composer.Compose(_builder);
}
}
diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs
index e4e02443eb..d7b143df38 100644
--- a/src/Umbraco.Core/Composing/CompositionExtensions.cs
+++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs
@@ -1,5 +1,4 @@
-using System;
-using Umbraco.Core;
+using System;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
using Umbraco.Web.PublishedCache;
diff --git a/src/Umbraco.Core/Composing/IPublishedCacheComposer .cs b/src/Umbraco.Core/Composing/IPublishedCacheComposer .cs
deleted file mode 100644
index d88eb44ea3..0000000000
--- a/src/Umbraco.Core/Composing/IPublishedCacheComposer .cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace Umbraco.Core.Composing
-{
- public interface IPublishedCacheComposer : ICoreComposer
- { }
-}
diff --git a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs
index edbf554a2c..9229a95cc3 100644
--- a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs
+++ b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.Composing
{
diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs
deleted file mode 100644
index 58aac7b811..0000000000
--- a/src/Umbraco.Core/CompositionExtensions.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Core.HealthCheck;
-using Umbraco.Core.Manifest;
-using Umbraco.Core.PropertyEditors;
-using Umbraco.Web.Actions;
-using Umbraco.Web.ContentApps;
-using Umbraco.Web.Dashboards;
-using Umbraco.Web.Editors;
-using Umbraco.Web.Routing;
-using Umbraco.Web.Sections;
-using Umbraco.Web.Tour;
-
-namespace Umbraco.Core
-{
- public static partial class CompositionExtensions
- {
-
- #region Collection Builders
-
- ///
- /// Gets the actions collection builder.
- ///
- /// The builder.
- ///
- public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the content apps collection builder.
- ///
- /// The builder.
- ///
- public static ContentAppFactoryCollectionBuilder ContentApps(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the content finders collection builder.
- ///
- /// The builder.
- ///
- public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the editor validators collection builder.
- ///
- /// The builder.
- ///
- public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the health checks collection builder.
- ///
- /// The builder.
- public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the TourFilters collection builder.
- ///
- public static TourFilterCollectionBuilder TourFilters(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the URL providers collection builder.
- ///
- /// The builder.
- public static UrlProviderCollectionBuilder UrlProviders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the media url providers collection builder.
- ///
- /// The builder.
- public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the backoffice sections/applications collection builder.
- ///
- /// The builder.
- public static SectionCollectionBuilder Sections(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the components collection builder.
- ///
- public static ComponentCollectionBuilder Components(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
-
- ///
- /// Gets the backoffice dashboards collection builder.
- ///
- /// The builder.
- public static DashboardCollectionBuilder Dashboards(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add();
-
-
- ///
- /// Gets the content finders collection builder.
- ///
- /// The builder.
- ///
- public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Infrastructure/Configuration/Extensions/HealthCheckSettingsExtensions.cs b/src/Umbraco.Core/Configuration/Extensions/HealthCheckSettingsExtensions.cs
similarity index 90%
rename from src/Umbraco.Infrastructure/Configuration/Extensions/HealthCheckSettingsExtensions.cs
rename to src/Umbraco.Core/Configuration/Extensions/HealthCheckSettingsExtensions.cs
index 92c3608ac1..ae842cb040 100644
--- a/src/Umbraco.Infrastructure/Configuration/Extensions/HealthCheckSettingsExtensions.cs
+++ b/src/Umbraco.Core/Configuration/Extensions/HealthCheckSettingsExtensions.cs
@@ -1,9 +1,7 @@
using System;
-using NCrontab;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
-namespace Umbraco.Infrastructure.Configuration.Extensions
+namespace Umbraco.Core.Configuration.Extensions
{
public static class HealthCheckSettingsExtensions
{
diff --git a/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs
new file mode 100644
index 0000000000..907b29490d
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+using System.Collections.Generic;
+
+namespace Umbraco.Core.Configuration.Models
+{
+ ///
+ /// Typed configuration options for the plugins.
+ ///
+ public class UmbracoPluginSettings
+ {
+ ///
+ /// Gets or sets the allowed file extensions (including the period ".") that should be accessible from the browser.
+ ///
+ public ISet BrowsableFileExtensions { get; set; } = new HashSet(new[]
+ {
+ ".html", // markup
+ ".css", // styles
+ ".js", // scripts
+ ".jpg", ".jpeg", ".gif", ".png", ".svg", // images
+ ".eot", ".ttf", ".woff", // fonts
+ ".xml", ".json", ".config", // configurations
+ ".lic" // license
+ });
+ }
+}
diff --git a/src/Umbraco.Core/Constants-Configuration.cs b/src/Umbraco.Core/Constants-Configuration.cs
index 2c9fe3caee..a60f29c39d 100644
--- a/src/Umbraco.Core/Constants-Configuration.cs
+++ b/src/Umbraco.Core/Constants-Configuration.cs
@@ -39,6 +39,7 @@
public const string ConfigMemberPassword = ConfigPrefix + "Security:MemberPassword";
public const string ConfigModelsBuilder = ConfigPrefix + "ModelsBuilder";
public const string ConfigNuCache = ConfigPrefix + "NuCache";
+ public const string ConfigPlugins = ConfigPrefix + "Plugins";
public const string ConfigRequestHandler = ConfigPrefix + "RequestHandler";
public const string ConfigRuntime = ConfigPrefix + "Runtime";
public const string ConfigRuntimeMinification = ConfigPrefix + "RuntimeMinification";
diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs
index 6145f4190b..464896edd9 100644
--- a/src/Umbraco.Core/Constants-SystemDirectories.cs
+++ b/src/Umbraco.Core/Constants-SystemDirectories.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Core
///
/// This is not the same as the Umbraco web folder which is configurable for serving front-end files.
///
- public const string Umbraco = "~/Umbraco";
+ public const string Umbraco = "~/umbraco";
///
/// The Umbraco data folder in the content root
diff --git a/src/Umbraco.Core/Constants-Web.cs b/src/Umbraco.Core/Constants-Web.cs
index 5d059d8a23..8199d9fbd0 100644
--- a/src/Umbraco.Core/Constants-Web.cs
+++ b/src/Umbraco.Core/Constants-Web.cs
@@ -1,4 +1,4 @@
-namespace Umbraco.Core
+namespace Umbraco.Core
{
public static partial class Constants
{
@@ -7,10 +7,6 @@
///
public static class Web
{
- public const string UmbracoContextDataToken = "umbraco-context";
- public const string UmbracoDataToken = "umbraco";
- public const string PublishedDocumentRequestDataToken = "umbraco-doc-request";
- public const string CustomRouteDataToken = "umbraco-custom-route";
public const string UmbracoRouteDefinitionDataToken = "umbraco-route-def";
///
diff --git a/src/Umbraco.Core/ServiceCollectionExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs
similarity index 89%
rename from src/Umbraco.Core/ServiceCollectionExtensions.cs
rename to src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs
index d1c89ea17e..97e70da9be 100644
--- a/src/Umbraco.Core/ServiceCollectionExtensions.cs
+++ b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs
@@ -1,9 +1,10 @@
-using System;
+using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
+using Umbraco.Core;
using Umbraco.Core.Composing;
-namespace Umbraco.Core
+namespace Umbraco.Core.DependencyInjection
{
public static class ServiceCollectionExtensions
{
@@ -21,7 +22,7 @@ namespace Umbraco.Core
where TImplementing : class, TService1, TService2
{
services.AddUnique();
- services.AddUnique(factory => (TImplementing) factory.GetRequiredService());
+ services.AddUnique(factory => (TImplementing)factory.GetRequiredService());
}
public static void AddUnique(this IServiceCollection services)
@@ -48,9 +49,9 @@ namespace Umbraco.Core
///
public static void AddUnique(this IServiceCollection services, TService instance)
where TService : class
- => services.Replace(ServiceDescriptor.Singleton(instance));
+ => services.Replace(ServiceDescriptor.Singleton(instance));
- public static IServiceCollection AddLazySupport(this IServiceCollection services)
+ internal static IServiceCollection AddLazySupport(this IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient(typeof(Lazy<>), typeof(LazyResolve<>)));
return services;
diff --git a/src/Umbraco.Core/ServiceProviderExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs
similarity index 96%
rename from src/Umbraco.Core/ServiceProviderExtensions.cs
rename to src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs
index e0d3da2c03..a1cc779500 100644
--- a/src/Umbraco.Core/ServiceProviderExtensions.cs
+++ b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs
@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
+using System;
using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core.Composing;
-namespace Umbraco.Core
+namespace Umbraco.Core.DependencyInjection
{
///
/// Provides extension methods to the class.
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs
new file mode 100644
index 0000000000..f6dc6fd6ff
--- /dev/null
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs
@@ -0,0 +1,275 @@
+using System.Security.Cryptography;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Dashboards;
+using Umbraco.Core.HealthCheck;
+using Umbraco.Core.Manifest;
+using Umbraco.Core.PackageActions;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.PropertyEditors.Validators;
+using Umbraco.Core.Strings;
+using Umbraco.Core.Trees;
+using Umbraco.Web.Actions;
+using Umbraco.Web.ContentApps;
+using Umbraco.Web.Dashboards;
+using Umbraco.Web.Editors;
+using Umbraco.Web.HealthCheck;
+using Umbraco.Web.HealthCheck.NotificationMethods;
+using Umbraco.Web.Media.EmbedProviders;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Sections;
+using Umbraco.Web.Tour;
+
+namespace Umbraco.Core.DependencyInjection
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Adds all core collection builders
+ ///
+ internal static void AddAllCoreCollectionBuilders(this IUmbracoBuilder builder)
+ {
+ builder.CacheRefreshers().Add(() => builder.TypeLoader.GetCacheRefreshers());
+ builder.DataEditors().Add(() => builder.TypeLoader.GetDataEditors());
+ builder.Actions().Add(() => builder.TypeLoader.GetTypes());
+ // register known content apps
+ builder.ContentApps()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append();
+ // all built-in finders in the correct order,
+ // devs can then modify this list on application startup
+ builder.ContentFinders()
+ .Append()
+ .Append()
+ .Append()
+ /*.Append() // disabled, this is an odd finder */
+ .Append()
+ .Append();
+ builder.EditorValidators().Add(() => builder.TypeLoader.GetTypes());
+ builder.HealthChecks().Add(() => builder.TypeLoader.GetTypes());
+ builder.HealthCheckNotificationMethods().Add(() => builder.TypeLoader.GetTypes());
+ builder.TourFilters();
+ builder.UrlProviders()
+ .Append()
+ .Append();
+ builder.MediaUrlProviders()
+ .Append();
+ // register back office sections in the order we want them rendered
+ builder.Sections()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append();
+ builder.Components();
+ // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards
+ builder.Dashboards()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add(builder.TypeLoader.GetTypes());
+ builder.PackageActions().Add(() => builder.TypeLoader.GetPackageActions());
+ builder.DataValueReferenceFactories();
+ builder.PropertyValueConverters().Append(builder.TypeLoader.GetTypes());
+ builder.UrlSegmentProviders().Append();
+ builder.ManifestValueValidators()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add();
+ builder.ManifestFilters();
+ builder.MediaUrlGenerators();
+ // register OEmbed providers - no type scanning - all explicit opt-in of adding types, IEmbedProvider is not IDiscoverable
+ builder.OEmbedProviders()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append();
+ builder.SearchableTrees().Add(() => builder.TypeLoader.GetTypes());
+ }
+
+ ///
+ /// Gets the actions collection builder.
+ ///
+ /// The builder.
+ public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the content apps collection builder.
+ ///
+ /// The builder.
+ public static ContentAppFactoryCollectionBuilder ContentApps(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the content finders collection builder.
+ ///
+ /// The builder.
+ public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the editor validators collection builder.
+ ///
+ /// The builder.
+ public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the health checks collection builder.
+ ///
+ /// The builder.
+ public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ public static HealthCheckNotificationMethodCollectionBuilder HealthCheckNotificationMethods(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the TourFilters collection builder.
+ ///
+ public static TourFilterCollectionBuilder TourFilters(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the URL providers collection builder.
+ ///
+ /// The builder.
+ public static UrlProviderCollectionBuilder UrlProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the media url providers collection builder.
+ ///
+ /// The builder.
+ public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the backoffice sections/applications collection builder.
+ ///
+ /// The builder.
+ public static SectionCollectionBuilder Sections(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the components collection builder.
+ ///
+ public static ComponentCollectionBuilder Components(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the backoffice dashboards collection builder.
+ ///
+ /// The builder.
+ public static DashboardCollectionBuilder Dashboards(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the cache refreshers collection builder.
+ ///
+ /// The builder.
+ public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the package actions collection builder.
+ ///
+ /// The builder.
+ internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the data editor collection builder.
+ ///
+ /// The builder.
+ public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the data value reference factory collection builder.
+ ///
+ /// The builder.
+ public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the property value converters collection builder.
+ ///
+ /// The builder.
+ public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the url segment providers collection builder.
+ ///
+ /// The builder.
+ public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the validators collection builder.
+ ///
+ /// The builder.
+ internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the manifest filter collection builder.
+ ///
+ /// The builder.
+ public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the content finders collection builder.
+ ///
+ /// The builder.
+ public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the backoffice OEmbed Providers collection builder.
+ ///
+ /// The builder.
+ public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the back office searchable tree collection builder
+ ///
+ public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+ }
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs
new file mode 100644
index 0000000000..5bd2fe9e8c
--- /dev/null
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.Logging;
+using Umbraco.Core.Composing;
+
+namespace Umbraco.Core.DependencyInjection
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Adds Umbraco composers for plugins
+ ///
+ public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder)
+ {
+ // TODO: Should have a better name
+
+ IEnumerable composerTypes = builder.TypeLoader.GetTypes();
+ IEnumerable enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute));
+ new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger()).Compose();
+
+ return builder;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs
new file mode 100644
index 0000000000..a31a44beeb
--- /dev/null
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Umbraco.Core.Configuration.Models;
+using Umbraco.Core.Configuration.Models.Validation;
+
+namespace Umbraco.Core.DependencyInjection
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Add Umbraco configuration services and options
+ ///
+ public static IUmbracoBuilder AddConfiguration(this IUmbracoBuilder builder)
+ {
+ // Register configuration validators.
+ builder.Services.AddSingleton, ContentSettingsValidator>();
+ builder.Services.AddSingleton, GlobalSettingsValidator>();
+ builder.Services.AddSingleton, HealthChecksSettingsValidator>();
+ builder.Services.AddSingleton, RequestHandlerSettingsValidator>();
+
+ // Register configuration sections.
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigActiveDirectory));
+ builder.Services.Configure(builder.Config.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true);
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigContent));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigCoreDebug));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExceptionFilter));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigGlobal));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHealthChecks));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHosting));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigImaging));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExamine));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigKeepAlive));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigLogging));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigMemberPassword));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigModelsBuilder), o => o.BindNonPublicProperties = true);
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigNuCache));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRequestHandler));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRuntime));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigSecurity));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTours));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigPlugins));
+
+ return builder;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
index a21ae74976..c24936b4fb 100644
--- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
@@ -2,6 +2,7 @@
// See LICENSE for more details.
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
using Umbraco.Core.Events;
namespace Umbraco.Core.DependencyInjection
@@ -23,7 +24,15 @@ namespace Umbraco.Core.DependencyInjection
where TNotification : INotification
{
// Register the handler as transient. This ensures that anything can be injected into it.
- builder.Services.AddTransient(typeof(INotificationHandler), typeof(TNotificationHandler));
+ var descriptor = new ServiceDescriptor(typeof(INotificationHandler), typeof(TNotificationHandler), ServiceLifetime.Transient);
+
+ // TODO: Waiting on feedback here https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 about whether
+ // we perform this duplicate check or not.
+ if (!builder.Services.Contains(descriptor))
+ {
+ builder.Services.Add(descriptor);
+ }
+
return builder;
}
}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
index d56712cdcf..96f01d111a 100644
--- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
@@ -3,28 +3,65 @@
using System;
using System.Collections.Generic;
+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.Core.Cache;
using Umbraco.Core.Composing;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.Grid;
+using Umbraco.Core.Configuration.Models;
+using Umbraco.Core.Diagnostics;
+using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Mail;
+using Umbraco.Core.Manifest;
+using Umbraco.Core.Models.PublishedContent;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Runtime;
+using Umbraco.Core.Security;
+using Umbraco.Core.Services;
+using Umbraco.Core.Sync;
+using Umbraco.Web;
+using Umbraco.Web.Cache;
+using Umbraco.Web.Editors;
+using Umbraco.Web.Features;
+using Umbraco.Web.Install;
+using Umbraco.Web.Models.PublishedContent;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Services;
+using Umbraco.Web.Templates;
namespace Umbraco.Core.DependencyInjection
{
public class UmbracoBuilder : IUmbracoBuilder
{
- public IServiceCollection Services { get; }
- public IConfiguration Config { get; }
- public TypeLoader TypeLoader { get; }
- public ILoggerFactory BuilderLoggerFactory { get; }
-
private readonly Dictionary _builders = new Dictionary();
+ public IServiceCollection Services { get; }
+
+ public IConfiguration Config { get; }
+
+ public TypeLoader TypeLoader { get; }
+
+ public ILoggerFactory BuilderLoggerFactory { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader)
: this(services, config, typeLoader, NullLoggerFactory.Instance)
{ }
+ ///
+ /// Initializes a new instance of the class.
+ ///
public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader, ILoggerFactory loggerFactory)
{
Services = services;
@@ -43,10 +80,12 @@ namespace Umbraco.Core.DependencyInjection
public TBuilder WithCollectionBuilder()
where TBuilder : ICollectionBuilder, new()
{
- var typeOfBuilder = typeof(TBuilder);
+ Type typeOfBuilder = typeof(TBuilder);
- if (_builders.TryGetValue(typeOfBuilder, out var o))
+ if (_builders.TryGetValue(typeOfBuilder, out ICollectionBuilder o))
+ {
return (TBuilder)o;
+ }
var builder = new TBuilder();
_builders[typeOfBuilder] = builder;
@@ -55,8 +94,10 @@ namespace Umbraco.Core.DependencyInjection
public void Build()
{
- foreach (var builder in _builders.Values)
+ foreach (ICollectionBuilder builder in _builders.Values)
+ {
builder.RegisterWith(Services);
+ }
_builders.Clear();
}
@@ -66,6 +107,115 @@ namespace Umbraco.Core.DependencyInjection
// Register as singleton to allow injection everywhere.
Services.AddSingleton(p => p.GetService);
Services.AddSingleton();
+
+ 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();
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique(factory =>
+ {
+ IHostingEnvironment hostingEnvironment = factory.GetRequiredService();
+
+ 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().RuntimeCache);
+ Services.AddUnique(factory => factory.GetRequiredService().RequestCache);
+ Services.AddUnique();
+ Services.AddUnique();
+
+ this.AddAllCoreCollectionBuilders();
+ this.AddNotificationHandler();
+
+ Services.AddSingleton();
+ this.AddNotificationHandler();
+
+ Services.AddUnique();
+
+ // by default, register a noop factory
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddSingleton(f => f.GetRequiredService().CreateDictionary());
+
+ Services.AddUnique();
+
+ Services.AddUnique();
+
+ // will be injected in controllers when needed to invoke rest endpoints on Our
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // Grid config is not a real config file as we know them
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // register properties fallback
+ Services.AddUnique();
+
+ Services.AddUnique();
+
+ // register published router
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // register distributed cache
+ Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService()));
+
+ // 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();
+
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // register a server registrar, by default it's the db registrar
+ Services.AddUnique(f =>
+ {
+ GlobalSettings globalSettings = f.GetRequiredService>().Value;
+ var singleServer = globalSettings.DisableElectionForSingleServer;
+ return singleServer
+ ? (IServerRoleAccessor)new SingleServerRoleAccessor()
+ : new ElectedServerRoleAccessor(f.GetRequiredService());
+ });
}
}
}
diff --git a/src/Umbraco.Infrastructure/Diagnostics/IMarchal.cs b/src/Umbraco.Core/Diagnostics/IMarchal.cs
similarity index 58%
rename from src/Umbraco.Infrastructure/Diagnostics/IMarchal.cs
rename to src/Umbraco.Core/Diagnostics/IMarchal.cs
index 30e6a9e619..cde4592b1b 100644
--- a/src/Umbraco.Infrastructure/Diagnostics/IMarchal.cs
+++ b/src/Umbraco.Core/Diagnostics/IMarchal.cs
@@ -7,6 +7,10 @@ namespace Umbraco.Core.Diagnostics
///
public interface IMarchal
{
+ ///
+ /// Retrieves a computer-independent description of an exception, and information about the state that existed for the thread when the exception occurred.
+ ///
+ /// A pointer to an EXCEPTION_POINTERS structure.
IntPtr GetExceptionPointers();
}
}
diff --git a/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs b/src/Umbraco.Core/Diagnostics/MiniDump.cs
similarity index 98%
rename from src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs
rename to src/Umbraco.Core/Diagnostics/MiniDump.cs
index f2f730078f..51f595bfb2 100644
--- a/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs
+++ b/src/Umbraco.Core/Diagnostics/MiniDump.cs
@@ -2,9 +2,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
-using Umbraco.Core.Composing;
using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
namespace Umbraco.Core.Diagnostics
{
@@ -12,7 +10,7 @@ namespace Umbraco.Core.Diagnostics
// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/
// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
- internal static class MiniDump
+ public static class MiniDump
{
private static readonly object LockO = new object();
@@ -92,7 +90,9 @@ namespace Umbraco.Core.Diagnostics
exp.ExceptionPointers = IntPtr.Zero;
if (withException)
+ {
exp.ExceptionPointers = marchal.GetExceptionPointers();
+ }
var bRet = exp.ExceptionPointers == IntPtr.Zero
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
diff --git a/src/Umbraco.Core/Diagnostics/NoopMarchal.cs b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs
new file mode 100644
index 0000000000..09629f9595
--- /dev/null
+++ b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Umbraco.Core.Diagnostics
+{
+ internal class NoopMarchal : IMarchal
+ {
+ public IntPtr GetExceptionPointers() => IntPtr.Zero;
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs
similarity index 98%
rename from src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionary.cs
rename to src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs
index b0690c944b..1f23ec645c 100644
--- a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionary.cs
+++ b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Dictionary
/// The ILocalizationService is the service used for interacting with this data from the database which isn't all that fast
/// (even though there is caching involved, if there's lots of dictionary items the caching is not great)
///
- public class DefaultCultureDictionary : ICultureDictionary
+ internal class DefaultCultureDictionary : ICultureDictionary
{
private readonly ILocalizationService _localizationService;
private readonly IAppCache _requestCache;
diff --git a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionaryFactory.cs b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionaryFactory.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionaryFactory.cs
rename to src/Umbraco.Core/Dictionary/UmbracoCultureDictionaryFactory.cs
index a2d1fa12d3..e2e30f3d76 100644
--- a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionaryFactory.cs
+++ b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionaryFactory.cs
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Dictionary
///
/// In the future this will allow use to potentially store dictionary items elsewhere and allows for maximum flexibility.
///
- internal class DefaultCultureDictionaryFactory : ICultureDictionaryFactory
+ public class DefaultCultureDictionaryFactory : ICultureDictionaryFactory
{
private readonly ILocalizationService _localizationService;
private readonly AppCaches _appCaches;
diff --git a/src/Umbraco.Core/DisposableObjectSlim.cs b/src/Umbraco.Core/DisposableObjectSlim.cs
index 4992f8bc0f..6874ad8001 100644
--- a/src/Umbraco.Core/DisposableObjectSlim.cs
+++ b/src/Umbraco.Core/DisposableObjectSlim.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace Umbraco.Core
{
@@ -6,8 +6,7 @@ namespace Umbraco.Core
/// Abstract implementation of managed IDisposable.
///
///
- /// This is for objects that do NOT have unmanaged resources. Use
- /// for objects that DO have unmanaged resources and need to deal with them when disposing.
+ /// This is for objects that do NOT have unmanaged resources.
///
/// Can also be used as a pattern for when inheriting is not possible.
///
@@ -19,35 +18,39 @@ namespace Umbraco.Core
///
public abstract class DisposableObjectSlim : IDisposable
{
- private readonly object _locko = new object();
-
- // gets a value indicating whether this instance is disposed.
- // for internal tests only (not thread safe)
+ ///
+ /// Gets a value indicating whether this instance is disposed.
+ ///
+ ///
+ /// for internal tests only (not thread safe)
+ ///
public bool Disposed { get; private set; }
- // implements IDisposable
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
+ ///
+ /// Disposes managed resources
+ ///
+ protected abstract void DisposeResources();
- private void Dispose(bool disposing)
+ ///
+ /// Disposes managed resources
+ ///
+ /// True if disposing via Dispose method and not a finalizer. Always true for this class.
+ protected virtual void Dispose(bool disposing)
{
- // can happen if the object construction failed
- if (_locko == null)
- return;
-
- lock (_locko)
+ if (!Disposed)
{
- if (Disposed) return;
+ if (disposing)
+ {
+ DisposeResources();
+ }
+
Disposed = true;
}
-
- if (disposing)
- DisposeResources();
}
- protected virtual void DisposeResources() { }
+ ///
+#pragma warning disable CA1063 // Implement IDisposable Correctly
+ public void Dispose() => Dispose(disposing: true); // We do not use GC.SuppressFinalize because this has no finalizer
+#pragma warning restore CA1063 // Implement IDisposable Correctly
}
}
diff --git a/src/Umbraco.Infrastructure/Editors/UserEditorAuthorizationHelper.cs b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Editors/UserEditorAuthorizationHelper.cs
rename to src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs
diff --git a/src/Umbraco.Core/Events/IEventAggregator.cs b/src/Umbraco.Core/Events/IEventAggregator.cs
index bd01ad0b57..d78aed36b7 100644
--- a/src/Umbraco.Core/Events/IEventAggregator.cs
+++ b/src/Umbraco.Core/Events/IEventAggregator.cs
@@ -22,27 +22,4 @@ namespace Umbraco.Core.Events
Task PublishAsync(TNotification notification, CancellationToken cancellationToken = default)
where TNotification : INotification;
}
-
- ///
- /// A marker interface to represent a notification.
- ///
- public interface INotification
- {
- }
-
- ///
- /// Defines a handler for a notification.
- ///
- /// The type of notification being handled.
- public interface INotificationHandler
- where TNotification : INotification
- {
- ///
- /// Handles a notification
- ///
- /// The notification
- /// The cancellation token.
- /// A representing the asynchronous operation.
- Task HandleAsync(TNotification notification, CancellationToken cancellationToken);
- }
}
diff --git a/src/Umbraco.Core/Events/INotification.cs b/src/Umbraco.Core/Events/INotification.cs
new file mode 100644
index 0000000000..3030b0836f
--- /dev/null
+++ b/src/Umbraco.Core/Events/INotification.cs
@@ -0,0 +1,12 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+namespace Umbraco.Core.Events
+{
+ ///
+ /// A marker interface to represent a notification.
+ ///
+ public interface INotification
+ {
+ }
+}
diff --git a/src/Umbraco.Core/Events/INotificationHandler.cs b/src/Umbraco.Core/Events/INotificationHandler.cs
new file mode 100644
index 0000000000..dc5d83e0f7
--- /dev/null
+++ b/src/Umbraco.Core/Events/INotificationHandler.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Umbraco.Core.Events
+{
+ ///
+ /// Defines a handler for a notification.
+ ///
+ /// The type of notification being handled.
+ public interface INotificationHandler
+ where TNotification : INotification
+ {
+ ///
+ /// Handles a notification
+ ///
+ /// The notification
+ /// The cancellation token.
+ /// A representing the asynchronous operation.
+ Task HandleAsync(TNotification notification, CancellationToken cancellationToken);
+ }
+}
diff --git a/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs b/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
new file mode 100644
index 0000000000..422673a823
--- /dev/null
+++ b/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
@@ -0,0 +1,16 @@
+namespace Umbraco.Core.Events
+{
+ public class UmbracoApplicationStarting : INotification
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The runtime level
+ public UmbracoApplicationStarting(RuntimeLevel runtimeLevel) => RuntimeLevel = runtimeLevel;
+
+ ///
+ /// Gets the runtime level of execution.
+ ///
+ public RuntimeLevel RuntimeLevel { get; }
+ }
+}
diff --git a/src/Umbraco.Core/Events/UmbracoApplicationStopping.cs b/src/Umbraco.Core/Events/UmbracoApplicationStopping.cs
new file mode 100644
index 0000000000..bef6f0de19
--- /dev/null
+++ b/src/Umbraco.Core/Events/UmbracoApplicationStopping.cs
@@ -0,0 +1,4 @@
+namespace Umbraco.Core.Events
+{
+ public class UmbracoApplicationStopping : INotification { }
+}
diff --git a/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs b/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs
index a22748094a..28e1de3996 100644
--- a/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs
+++ b/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs
@@ -32,22 +32,16 @@ namespace Umbraco.Core.HealthCheck.Checks.Permissions
///
/// Get the status for this health check
///
- ///
- public override IEnumerable GetStatus()
- {
- //return the statuses
- return new[] { CheckFolderPermissions(), CheckFilePermissions() };
- }
+ // TODO: This should really just run the IFilePermissionHelper.RunFilePermissionTestSuite and then we'd have a
+ // IFilePermissions interface resolved as a collection within the IFilePermissionHelper that runs checks against all
+ // IFilePermissions registered. Then there's no hard coding things done here and the checks here will be consistent
+ // with the checks run in IFilePermissionHelper.RunFilePermissionTestSuite which occurs on install too.
+ public override IEnumerable GetStatus() => new[] { CheckFolderPermissions(), CheckFilePermissions() };
///
/// Executes the action and returns it's status
///
- ///
- ///
- public override HealthCheckStatus ExecuteAction(HealthCheckAction action)
- {
- throw new InvalidOperationException("FolderAndFilePermissionsCheck has no executable actions");
- }
+ public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("FolderAndFilePermissionsCheck has no executable actions");
private HealthCheckStatus CheckFolderPermissions()
{
@@ -67,8 +61,8 @@ namespace Umbraco.Core.HealthCheck.Checks.Permissions
{ Constants.SystemDirectories.MvcViews, PermissionCheckRequirement.Optional }
};
- //These are special paths to check that will restart an app domain if a file is written to them,
- //so these need to be tested differently
+ // These are special paths to check that will restart an app domain if a file is written to them,
+ // so these need to be tested differently
var pathsToCheckWithRestarts = new Dictionary
{
{ Constants.SystemDirectories.Bin, PermissionCheckRequirement.Optional }
@@ -80,7 +74,7 @@ namespace Umbraco.Core.HealthCheck.Checks.Permissions
var optionalPathCheckResult = _filePermissionHelper.EnsureDirectories(
GetPathsToCheck(pathsToCheck, PermissionCheckRequirement.Optional), out var optionalFailedPaths);
- //now check the special folders
+ // now check the special folders
var requiredPathCheckResult2 = _filePermissionHelper.EnsureDirectories(
GetPathsToCheck(pathsToCheckWithRestarts, PermissionCheckRequirement.Required), out var requiredFailedPaths2, writeCausesRestart: true);
var optionalPathCheckResult2 = _filePermissionHelper.EnsureDirectories(
@@ -89,7 +83,7 @@ namespace Umbraco.Core.HealthCheck.Checks.Permissions
requiredPathCheckResult = requiredPathCheckResult && requiredPathCheckResult2;
optionalPathCheckResult = optionalPathCheckResult && optionalPathCheckResult2;
- //combine the paths
+ // combine the paths
requiredFailedPaths = requiredFailedPaths.Concat(requiredFailedPaths2).ToList();
optionalFailedPaths = requiredFailedPaths.Concat(optionalFailedPaths2).ToList();
@@ -106,23 +100,19 @@ namespace Umbraco.Core.HealthCheck.Checks.Permissions
};
// Run checks for required and optional paths for modify permission
- IEnumerable requiredFailedPaths;
- IEnumerable optionalFailedPaths;
- var requiredPathCheckResult = _filePermissionHelper.EnsureFiles(GetPathsToCheck(pathsToCheck, PermissionCheckRequirement.Required), out requiredFailedPaths);
- var optionalPathCheckResult = _filePermissionHelper.EnsureFiles(GetPathsToCheck(pathsToCheck, PermissionCheckRequirement.Optional), out optionalFailedPaths);
+ var requiredPathCheckResult = _filePermissionHelper.EnsureFiles(GetPathsToCheck(pathsToCheck, PermissionCheckRequirement.Required), out IEnumerable requiredFailedPaths);
+ var optionalPathCheckResult = _filePermissionHelper.EnsureFiles(GetPathsToCheck(pathsToCheck, PermissionCheckRequirement.Optional), out IEnumerable optionalFailedPaths);
return GetStatus(requiredPathCheckResult, requiredFailedPaths, optionalPathCheckResult, optionalFailedPaths, PermissionCheckFor.File);
}
- private string[] GetPathsToCheck(Dictionary pathsToCheck,
- PermissionCheckRequirement requirement)
- {
- return pathsToCheck
+ private string[] GetPathsToCheck(
+ Dictionary pathsToCheck,
+ PermissionCheckRequirement requirement) => pathsToCheck
.Where(x => x.Value == requirement)
.Select(x => _hostingEnvironment.MapPathContentRoot(x.Key))
.OrderBy(x => x)
.ToArray();
- }
private HealthCheckStatus GetStatus(bool requiredPathCheckResult, IEnumerable requiredFailedPaths, bool optionalPathCheckResult, IEnumerable optionalFailedPaths, PermissionCheckFor checkingFor)
{
diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollection.cs b/src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollection.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollection.cs
rename to src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollection.cs
diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs
rename to src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs
diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs b/src/Umbraco.Core/HealthCheck/HealthCheckResults.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs
rename to src/Umbraco.Core/HealthCheck/HealthCheckResults.cs
index 37159b4a49..44955bfaae 100644
--- a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs
+++ b/src/Umbraco.Core/HealthCheck/HealthCheckResults.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using HeyRed.MarkdownSharp;
using Microsoft.Extensions.Logging;
using Umbraco.Core;
using Umbraco.Core.HealthCheck;
@@ -120,33 +119,9 @@ namespace Umbraco.Infrastructure.HealthCheck
return sb.ToString();
}
- public string ResultsAsHtml(HealthCheckNotificationVerbosity verbosity)
- {
- var mark = new Markdown();
- var html = mark.Transform(ResultsAsMarkDown(verbosity));
- html = ApplyHtmlHighlighting(html);
- return html;
- }
internal Dictionary> ResultsAsDictionary => _results;
- private string ApplyHtmlHighlighting(string html)
- {
- const string SuccessHexColor = "5cb85c";
- const string WarningHexColor = "f0ad4e";
- const string ErrorHexColor = "d9534f";
-
- html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Success, SuccessHexColor);
- html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Warning, WarningHexColor);
- return ApplyHtmlHighlightingForStatus(html, StatusResultType.Error, ErrorHexColor);
- }
-
- private string ApplyHtmlHighlightingForStatus(string html, StatusResultType status, string color)
- {
- return html
- .Replace("Result: '" + status + "'", "Result: " + status + "");
- }
-
private string SimpleHtmlToMarkDown(string html)
{
return html.Replace("", "**")
diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
similarity index 89%
rename from src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
rename to src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
index 4d7444447f..ad92886ecd 100644
--- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
+++ b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
@@ -5,6 +5,7 @@ using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.HealthCheck;
+using Umbraco.Core.Mail;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Infrastructure.HealthCheck;
@@ -17,6 +18,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
private readonly ILocalizedTextService _textService;
private readonly IRequestAccessor _requestAccessor;
private readonly IEmailSender _emailSender;
+ private readonly IMarkdownToHtmlConverter _markdownToHtmlConverter;
private readonly ContentSettings _contentSettings;
@@ -25,7 +27,8 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
IRequestAccessor requestAccessor,
IEmailSender emailSender,
IOptions healthChecksSettings,
- IOptions contentSettings)
+ IOptions contentSettings,
+ IMarkdownToHtmlConverter markdownToHtmlConverter)
: base(healthChecksSettings)
{
var recipientEmail = Settings?["RecipientEmail"];
@@ -40,6 +43,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
_textService = textService ?? throw new ArgumentNullException(nameof(textService));
_requestAccessor = requestAccessor;
_emailSender = emailSender;
+ _markdownToHtmlConverter = markdownToHtmlConverter;
_contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings));
}
@@ -61,7 +65,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
{
DateTime.Now.ToShortDateString(),
DateTime.Now.ToShortTimeString(),
- results.ResultsAsHtml(Verbosity)
+ _markdownToHtmlConverter.ToHtml(results, Verbosity)
});
// Include the umbraco Application URL host in the message subject so that
diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs
rename to src/Umbraco.Core/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs
diff --git a/src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs
new file mode 100644
index 0000000000..20d8f0f07e
--- /dev/null
+++ b/src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs
@@ -0,0 +1,10 @@
+using Umbraco.Core.HealthCheck;
+using Umbraco.Infrastructure.HealthCheck;
+
+namespace Umbraco.Web.HealthCheck.NotificationMethods
+{
+ public interface IMarkdownToHtmlConverter
+ {
+ string ToHtml(HealthCheckResults results, HealthCheckNotificationVerbosity verbosity);
+ }
+}
diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/NotificationMethodBase.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs
rename to src/Umbraco.Core/HealthCheck/NotificationMethods/NotificationMethodBase.cs
diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs
similarity index 73%
rename from src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
rename to src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs
index a032720d46..a4368a2634 100644
--- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
+++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs
@@ -1,25 +1,20 @@
using System;
-namespace Umbraco.Net
+namespace Umbraco.Core.Hosting
{
- // TODO: This shouldn't be in this namespace?
public interface IUmbracoApplicationLifetime
{
///
/// A value indicating whether the application is restarting after the current request.
///
bool IsRestarting { get; }
+
///
/// Terminates the current application. The application restarts the next time a request is received for it.
///
void Restart();
+ // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications
event EventHandler ApplicationInit;
}
-
-
- public interface IUmbracoApplicationLifetimeManager
- {
- void InvokeApplicationInit();
- }
}
diff --git a/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs
new file mode 100644
index 0000000000..778edc24dd
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Core.Hosting
+{
+ // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications
+ public interface IUmbracoApplicationLifetimeManager
+ {
+ void InvokeApplicationInit();
+ }
+}
diff --git a/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs
new file mode 100644
index 0000000000..3ffef04410
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Core.Hosting
+{
+ internal class NoopApplicationShutdownRegistry : IApplicationShutdownRegistry
+ {
+ public void RegisterObject(IRegisteredObject registeredObject) { }
+ public void UnregisterObject(IRegisteredObject registeredObject) { }
+ }
+}
diff --git a/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs b/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs
new file mode 100644
index 0000000000..7833fd1224
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs
@@ -0,0 +1,7 @@
+namespace Umbraco.Core.Hosting
+{
+ internal class NoopUmbracoApplicationLifetimeManager : IUmbracoApplicationLifetimeManager
+ {
+ public void InvokeApplicationInit() { }
+ }
+}
diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs
index b078172213..62f46edce4 100644
--- a/src/Umbraco.Core/IO/FileSystems.cs
+++ b/src/Umbraco.Core/IO/FileSystems.cs
@@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging;
using Umbraco.Core.Hosting;
using Umbraco.Core.Configuration.Models;
using Microsoft.Extensions.Options;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.IO
{
diff --git a/src/Umbraco.Core/Install/IFilePermissionHelper.cs b/src/Umbraco.Core/Install/IFilePermissionHelper.cs
index b60839cb00..ab521d214e 100644
--- a/src/Umbraco.Core/Install/IFilePermissionHelper.cs
+++ b/src/Umbraco.Core/Install/IFilePermissionHelper.cs
@@ -1,11 +1,26 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace Umbraco.Core.Install
{
public interface IFilePermissionHelper
{
bool RunFilePermissionTestSuite(out Dictionary> report);
+
+ ///
+ /// This will test the directories for write access
+ ///
+ /// The directories to check
+ /// The resulting errors, if any
+ ///
+ /// If this is false, the easiest way to test for write access is to write a temp file, however some folder will cause
+ /// an App Domain restart if a file is written to the folder, so in that case we need to use the ACL APIs which aren't as
+ /// reliable but we cannot write a file since it will cause an app domain restart.
+ ///
+ /// Returns true if test succeeds
+ // TODO: This shouldn't exist, see notes in FolderAndFilePermissionsCheck.GetStatus
bool EnsureDirectories(string[] dirs, out IEnumerable errors, bool writeCausesRestart = false);
+
+ // TODO: This shouldn't exist, see notes in FolderAndFilePermissionsCheck.GetStatus
bool EnsureFiles(string[] files, out IEnumerable errors);
}
}
diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs
similarity index 98%
rename from src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs
rename to src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs
index 4cd25c16bb..4866c472e6 100644
--- a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs
+++ b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs
@@ -2,11 +2,10 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Umbraco.Core.Hosting;
using Umbraco.Core.Security;
-using Umbraco.Net;
using Umbraco.Core.Services;
using Umbraco.Web.Install.Models;
-using Umbraco.Web.Security;
namespace Umbraco.Web.Install.InstallSteps
{
diff --git a/src/Umbraco.Infrastructure/Install/Models/InstallInstructions.cs b/src/Umbraco.Core/Install/Models/InstallInstructions.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Install/Models/InstallInstructions.cs
rename to src/Umbraco.Core/Install/Models/InstallInstructions.cs
diff --git a/src/Umbraco.Core/Logging/VoidProfiler.cs b/src/Umbraco.Core/Logging/NoopProfiler.cs
similarity index 89%
rename from src/Umbraco.Core/Logging/VoidProfiler.cs
rename to src/Umbraco.Core/Logging/NoopProfiler.cs
index d771fd7630..e7b43e5e2d 100644
--- a/src/Umbraco.Core/Logging/VoidProfiler.cs
+++ b/src/Umbraco.Core/Logging/NoopProfiler.cs
@@ -1,8 +1,8 @@
-using System;
+using System;
namespace Umbraco.Core.Logging
{
- public class VoidProfiler : IProfiler
+ public class NoopProfiler : IProfiler
{
private readonly VoidDisposable _disposable = new VoidDisposable();
diff --git a/src/Umbraco.Core/IEmailSender.cs b/src/Umbraco.Core/Mail/IEmailSender.cs
similarity index 78%
rename from src/Umbraco.Core/IEmailSender.cs
rename to src/Umbraco.Core/Mail/IEmailSender.cs
index aab944e04d..3862d0e717 100644
--- a/src/Umbraco.Core/IEmailSender.cs
+++ b/src/Umbraco.Core/Mail/IEmailSender.cs
@@ -1,7 +1,7 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Umbraco.Core.Models;
-namespace Umbraco.Core
+namespace Umbraco.Core.Mail
{
///
/// Simple abstraction to send an email message
diff --git a/src/Umbraco.Core/ISmsSender.cs b/src/Umbraco.Core/Mail/ISmsSender.cs
similarity index 84%
rename from src/Umbraco.Core/ISmsSender.cs
rename to src/Umbraco.Core/Mail/ISmsSender.cs
index f296a2ea9b..a2ff054c48 100644
--- a/src/Umbraco.Core/ISmsSender.cs
+++ b/src/Umbraco.Core/Mail/ISmsSender.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
-namespace Umbraco.Core
+namespace Umbraco.Core.Mail
{
///
/// Service to send an SMS
diff --git a/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs
new file mode 100644
index 0000000000..bb8d787cbf
--- /dev/null
+++ b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Threading.Tasks;
+using Umbraco.Core.Models;
+
+namespace Umbraco.Core.Mail
+{
+ internal class NotImplementedEmailSender : IEmailSender
+ {
+ public Task SendAsync(EmailMessage message)
+ => throw new NotImplementedException("To send an Email ensure IEmailSender is implemented with a custom implementation");
+ }
+}
diff --git a/src/Umbraco.Infrastructure/NotImplementedSmsSender.cs b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs
similarity index 90%
rename from src/Umbraco.Infrastructure/NotImplementedSmsSender.cs
rename to src/Umbraco.Core/Mail/NotImplementedSmsSender.cs
index ffc33373d0..16c3d04711 100644
--- a/src/Umbraco.Infrastructure/NotImplementedSmsSender.cs
+++ b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs
@@ -1,7 +1,7 @@
-using System;
+using System;
using System.Threading.Tasks;
-namespace Umbraco.Core
+namespace Umbraco.Core.Mail
{
///
/// An that throws
diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs
index 6bd893d298..b6cd82b31f 100644
--- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs
+++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs
@@ -1,14 +1,13 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Extensions.Logging;
using Umbraco.Core.Hosting;
-using Umbraco.Net;
namespace Umbraco.Core.Manifest
{
- public class ManifestWatcher : DisposableObjectSlim
+ public class ManifestWatcher : IDisposable
{
private static readonly object Locker = new object();
private static volatile bool _isRestarting;
@@ -16,6 +15,7 @@ namespace Umbraco.Core.Manifest
private readonly ILogger _logger;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly List _fws = new List();
+ private bool _disposed;
public ManifestWatcher(ILogger logger, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
@@ -48,7 +48,10 @@ namespace Umbraco.Core.Manifest
private void FswChanged(object sender, FileSystemEventArgs e)
{
- if (e.Name.InvariantContains("package.manifest") == false) return;
+ if (!e.Name.InvariantContains("package.manifest"))
+ {
+ return;
+ }
// ensure the app is not restarted multiple times for multiple
// savings during the same app domain execution - restart once
@@ -59,14 +62,25 @@ namespace Umbraco.Core.Manifest
_isRestarting = true;
_logger.LogInformation("Manifest has changed, app pool is restarting ({Path})", e.FullPath);
_umbracoApplicationLifetime.Restart();
- Dispose(); // uh? if the app restarts then this should be disposed anyways?
}
}
- protected override void DisposeResources()
+ private void Dispose(bool disposing)
{
- foreach (var fw in _fws)
- fw.Dispose();
+ // ReSharper disable InvertIf
+ if (disposing && !_disposed)
+ {
+ foreach (FileSystemWatcher fw in _fws)
+ {
+ fw.Dispose();
+ }
+
+ _disposed = true;
+ }
+
+ // ReSharper restore InvertIf
}
+
+ public void Dispose() => Dispose(true);
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/DailyMotion.cs b/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs
similarity index 86%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/DailyMotion.cs
rename to src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs
index 78ea0b8662..f56a29c2d5 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/DailyMotion.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders
{
@"dailymotion.com/video/.*"
};
-
+
public override Dictionary RequestParams => new Dictionary()
{
//ApiUrl/?format=xml
@@ -24,5 +25,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return GetXmlProperty(xmlDocument, "/oembed/html");
}
+
+ public DailyMotion(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProviderBase.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs
similarity index 88%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProviderBase.cs
rename to src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs
index 539c01f69b..cc7f5d2349 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProviderBase.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs
@@ -1,16 +1,23 @@
-using Newtonsoft.Json;
-using System;
+using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Xml;
using Umbraco.Core.Media;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
public abstract class EmbedProviderBase : IEmbedProvider
{
+ private readonly IJsonSerializer _jsonSerializer;
+
+ protected EmbedProviderBase(IJsonSerializer jsonSerializer)
+ {
+ _jsonSerializer = jsonSerializer;
+ }
+
private static HttpClient _httpClient;
public abstract string ApiEndpoint { get; }
@@ -58,7 +65,7 @@ namespace Umbraco.Web.Media.EmbedProviders
public virtual T GetJsonResponse(string url) where T : class
{
var response = DownloadResponse(url);
- return JsonConvert.DeserializeObject(response);
+ return _jsonSerializer.Deserialize(response);
}
public virtual XmlDocument GetXmlResponse(string url)
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollection.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollection.cs
rename to src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs
rename to src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Flickr.cs b/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs
similarity index 90%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Flickr.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Flickr.cs
index d067060014..a6ead2df3a 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Flickr.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Net;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -27,5 +28,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return string.Format("
", imageUrl, imageWidth, imageHeight, WebUtility.HtmlEncode(imageTitle));
}
+
+ public Flickr(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/GettyImages.cs b/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs
similarity index 86%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/GettyImages.cs
rename to src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs
index 34b383614d..0db0a97b8e 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/GettyImages.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -23,5 +24,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return oembed.GetHtml();
}
+
+ public GettyImages(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Giphy.cs b/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs
similarity index 83%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Giphy.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Giphy.cs
index 1069de749c..319afda5b6 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Giphy.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs
@@ -1,8 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -28,5 +25,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return oembed.GetHtml();
}
+
+ public Giphy(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Hulu.cs b/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Hulu.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Hulu.cs
index 150439832a..4deea8c23d 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Hulu.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders
{
@"hulu.com/watch/.*"
};
-
+
public override Dictionary RequestParams => new Dictionary();
public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0)
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return oembed.GetHtml();
}
+
+ public Hulu(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Issuu.cs b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs
similarity index 86%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Issuu.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Issuu.cs
index 2b33473453..3baaf7ea35 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Issuu.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders
{
@"issuu.com/.*/docs/.*"
};
-
+
public override Dictionary RequestParams => new Dictionary()
{
//ApiUrl/?format=xml
@@ -24,5 +25,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return GetXmlProperty(xmlDocument, "/oembed/html");
}
+
+ public Issuu(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Kickstarter.cs b/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs
similarity index 84%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Kickstarter.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs
index 4de45ae2e3..ef75b6ebe8 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Kickstarter.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return oembed.GetHtml();
}
+
+ public Kickstarter(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/OEmbedResponse.cs b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs
similarity index 78%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/OEmbedResponse.cs
rename to src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs
index cc3e34931e..8178a97742 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/OEmbedResponse.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs
@@ -1,11 +1,12 @@
using System.Net;
-using Newtonsoft.Json;
+using System.Runtime.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
///
/// Wrapper class for OEmbed response
///
+ [DataContract]
public class OEmbedResponse
{
public string Type { get; set; }
@@ -14,25 +15,25 @@ namespace Umbraco.Web.Media.EmbedProviders
public string Title { get; set; }
- [JsonProperty("author_name")]
+ [DataMember(Name ="author_name")]
public string AuthorName { get; set; }
- [JsonProperty("author_url")]
+ [DataMember(Name ="author_url")]
public string AuthorUrl { get; set; }
- [JsonProperty("provider_name")]
+ [DataMember(Name ="provider_name")]
public string ProviderName { get; set; }
- [JsonProperty("provider_url")]
+ [DataMember(Name ="provider_url")]
public string ProviderUrl { get; set; }
- [JsonProperty("thumbnail_url")]
+ [DataMember(Name ="thumbnail_url")]
public string ThumbnailUrl { get; set; }
- [JsonProperty("thumbnail_height")]
+ [DataMember(Name ="thumbnail_height")]
public double? ThumbnailHeight { get; set; }
- [JsonProperty("thumbnail_width")]
+ [DataMember(Name ="thumbnail_width")]
public double? ThumbnailWidth { get; set; }
public string Html { get; set; }
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Slideshare.cs b/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Slideshare.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs
index 6d3a010c7a..7fa149d145 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Slideshare.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return GetXmlProperty(xmlDocument, "/oembed/html");
}
+
+ public Slideshare(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/SoundCloud.cs b/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs
similarity index 84%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/SoundCloud.cs
rename to src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs
index 080437a246..43cc92b0b4 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/SoundCloud.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders
{
@"soundcloud.com\/*"
};
-
+
public override Dictionary RequestParams => new Dictionary();
public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0)
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return GetXmlProperty(xmlDocument, "/oembed/html");
}
+
+ public Soundcloud(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Ted.cs b/src/Umbraco.Core/Media/EmbedProviders/Ted.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Ted.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Ted.cs
index aa14423349..cd4b78d065 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Ted.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Ted.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders
{
@"ted.com\/talks\/*"
};
-
+
public override Dictionary RequestParams => new Dictionary();
public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0)
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return GetXmlProperty(xmlDocument, "/oembed/html");
}
+
+ public Ted(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Twitter.cs b/src/Umbraco.Core/Media/EmbedProviders/Twitter.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Twitter.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Twitter.cs
index 9286934a4d..2bb4203411 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Twitter.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Twitter.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return oembed.GetHtml();
}
+
+ public Twitter(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Vimeo.cs b/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Vimeo.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs
index 806f40a10c..709ba61b3b 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Vimeo.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders
{
@"vimeo\.com/"
};
-
+
public override Dictionary RequestParams => new Dictionary();
public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0)
@@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return GetXmlProperty(xmlDocument, "/oembed/html");
}
+
+ public Vimeo(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Youtube.cs b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs
similarity index 86%
rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Youtube.cs
rename to src/Umbraco.Core/Media/EmbedProviders/Youtube.cs
index 4e6f437047..30b83caa88 100644
--- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Youtube.cs
+++ b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.Media.EmbedProviders
{
@@ -11,7 +12,7 @@ namespace Umbraco.Web.Media.EmbedProviders
@"youtu.be/.*",
@"youtube.com/watch.*"
};
-
+
public override Dictionary RequestParams => new Dictionary()
{
//ApiUrl/?format=json
@@ -25,5 +26,9 @@ namespace Umbraco.Web.Media.EmbedProviders
return oembed.GetHtml();
}
+
+ public YouTube(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/Exif/BitConverterEx.cs b/src/Umbraco.Core/Media/Exif/BitConverterEx.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/BitConverterEx.cs
rename to src/Umbraco.Core/Media/Exif/BitConverterEx.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifBitConverter.cs b/src/Umbraco.Core/Media/Exif/ExifBitConverter.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifBitConverter.cs
rename to src/Umbraco.Core/Media/Exif/ExifBitConverter.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifEnums.cs b/src/Umbraco.Core/Media/Exif/ExifEnums.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifEnums.cs
rename to src/Umbraco.Core/Media/Exif/ExifEnums.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifExceptions.cs b/src/Umbraco.Core/Media/Exif/ExifExceptions.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifExceptions.cs
rename to src/Umbraco.Core/Media/Exif/ExifExceptions.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifExtendedProperty.cs b/src/Umbraco.Core/Media/Exif/ExifExtendedProperty.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifExtendedProperty.cs
rename to src/Umbraco.Core/Media/Exif/ExifExtendedProperty.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifFileTypeDescriptor.cs b/src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifFileTypeDescriptor.cs
rename to src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifInterOperability.cs b/src/Umbraco.Core/Media/Exif/ExifInterOperability.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifInterOperability.cs
rename to src/Umbraco.Core/Media/Exif/ExifInterOperability.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifProperty.cs b/src/Umbraco.Core/Media/Exif/ExifProperty.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifProperty.cs
rename to src/Umbraco.Core/Media/Exif/ExifProperty.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifPropertyCollection.cs b/src/Umbraco.Core/Media/Exif/ExifPropertyCollection.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifPropertyCollection.cs
rename to src/Umbraco.Core/Media/Exif/ExifPropertyCollection.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifPropertyFactory.cs b/src/Umbraco.Core/Media/Exif/ExifPropertyFactory.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifPropertyFactory.cs
rename to src/Umbraco.Core/Media/Exif/ExifPropertyFactory.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifTag.cs b/src/Umbraco.Core/Media/Exif/ExifTag.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifTag.cs
rename to src/Umbraco.Core/Media/Exif/ExifTag.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifTagFactory.cs b/src/Umbraco.Core/Media/Exif/ExifTagFactory.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ExifTagFactory.cs
rename to src/Umbraco.Core/Media/Exif/ExifTagFactory.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/IFD.cs b/src/Umbraco.Core/Media/Exif/IFD.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/IFD.cs
rename to src/Umbraco.Core/Media/Exif/IFD.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFile.cs b/src/Umbraco.Core/Media/Exif/ImageFile.cs
similarity index 94%
rename from src/Umbraco.Infrastructure/Media/Exif/ImageFile.cs
rename to src/Umbraco.Core/Media/Exif/ImageFile.cs
index acd8ce8eec..f59f9dc73f 100644
--- a/src/Umbraco.Infrastructure/Media/Exif/ImageFile.cs
+++ b/src/Umbraco.Core/Media/Exif/ImageFile.cs
@@ -1,5 +1,4 @@
using System.ComponentModel;
-using System.Drawing;
using System.IO;
using System.Text;
using Umbraco.Web.Media.TypeDetector;
@@ -52,11 +51,6 @@ namespace Umbraco.Web.Media.Exif
#endregion
#region Instance Methods
- ///
- /// Converts the to a .
- ///
- /// Returns a containing image data.
- public abstract Image ToImage ();
///
/// Saves the to the specified file.
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectory.cs b/src/Umbraco.Core/Media/Exif/ImageFileDirectory.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectory.cs
rename to src/Umbraco.Core/Media/Exif/ImageFileDirectory.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectoryEntry.cs b/src/Umbraco.Core/Media/Exif/ImageFileDirectoryEntry.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectoryEntry.cs
rename to src/Umbraco.Core/Media/Exif/ImageFileDirectoryEntry.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFileFormat.cs b/src/Umbraco.Core/Media/Exif/ImageFileFormat.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/ImageFileFormat.cs
rename to src/Umbraco.Core/Media/Exif/ImageFileFormat.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JFIFEnums.cs b/src/Umbraco.Core/Media/Exif/JFIFEnums.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/JFIFEnums.cs
rename to src/Umbraco.Core/Media/Exif/JFIFEnums.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JFIFExtendedProperty.cs b/src/Umbraco.Core/Media/Exif/JFIFExtendedProperty.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/JFIFExtendedProperty.cs
rename to src/Umbraco.Core/Media/Exif/JFIFExtendedProperty.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JFIFThumbnail.cs b/src/Umbraco.Core/Media/Exif/JFIFThumbnail.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/JFIFThumbnail.cs
rename to src/Umbraco.Core/Media/Exif/JFIFThumbnail.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGExceptions.cs b/src/Umbraco.Core/Media/Exif/JPEGExceptions.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/JPEGExceptions.cs
rename to src/Umbraco.Core/Media/Exif/JPEGExceptions.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGFile.cs b/src/Umbraco.Core/Media/Exif/JPEGFile.cs
similarity index 99%
rename from src/Umbraco.Infrastructure/Media/Exif/JPEGFile.cs
rename to src/Umbraco.Core/Media/Exif/JPEGFile.cs
index 35c3788abd..83e6a81eec 100644
--- a/src/Umbraco.Infrastructure/Media/Exif/JPEGFile.cs
+++ b/src/Umbraco.Core/Media/Exif/JPEGFile.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Drawing;
using System.IO;
using System.Text;
@@ -260,15 +259,6 @@ namespace Umbraco.Web.Media.Exif
Save(stream, true);
}
- ///
- /// Returns a System.Drawing.Image created with image data.
- ///
- public override Image ToImage()
- {
- MemoryStream stream = new MemoryStream();
- Save(stream);
- return Image.FromStream(stream);
- }
#endregion
#region Private Helper Methods
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGMarker.cs b/src/Umbraco.Core/Media/Exif/JPEGMarker.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/JPEGMarker.cs
rename to src/Umbraco.Core/Media/Exif/JPEGMarker.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGSection.cs b/src/Umbraco.Core/Media/Exif/JPEGSection.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/JPEGSection.cs
rename to src/Umbraco.Core/Media/Exif/JPEGSection.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/MathEx.cs b/src/Umbraco.Core/Media/Exif/MathEx.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/MathEx.cs
rename to src/Umbraco.Core/Media/Exif/MathEx.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/SvgFile.cs b/src/Umbraco.Core/Media/Exif/SvgFile.cs
similarity index 86%
rename from src/Umbraco.Infrastructure/Media/Exif/SvgFile.cs
rename to src/Umbraco.Core/Media/Exif/SvgFile.cs
index 8916ac0801..1213bb513f 100644
--- a/src/Umbraco.Infrastructure/Media/Exif/SvgFile.cs
+++ b/src/Umbraco.Core/Media/Exif/SvgFile.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Drawing;
-using System.IO;
+using System.IO;
using System.Linq;
using System.Xml.Linq;
@@ -29,9 +27,5 @@ namespace Umbraco.Web.Media.Exif
{
}
- public override Image ToImage()
- {
- throw new NotImplementedException();
- }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/Exif/TIFFFile.cs b/src/Umbraco.Core/Media/Exif/TIFFFile.cs
similarity index 93%
rename from src/Umbraco.Infrastructure/Media/Exif/TIFFFile.cs
rename to src/Umbraco.Core/Media/Exif/TIFFFile.cs
index 4f5301d526..19575eaff2 100644
--- a/src/Umbraco.Infrastructure/Media/Exif/TIFFFile.cs
+++ b/src/Umbraco.Core/Media/Exif/TIFFFile.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Drawing;
using System.IO;
namespace Umbraco.Web.Media.Exif
@@ -162,16 +161,6 @@ namespace Umbraco.Web.Media.Exif
}
}
- ///
- /// Converts the to a .
- ///
- /// Returns a containing image data.
- public override Image ToImage()
- {
- MemoryStream stream = new MemoryStream();
- Save(stream);
- return Image.FromStream(stream);
- }
#endregion
}
}
diff --git a/src/Umbraco.Infrastructure/Media/Exif/TIFFHeader.cs b/src/Umbraco.Core/Media/Exif/TIFFHeader.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/TIFFHeader.cs
rename to src/Umbraco.Core/Media/Exif/TIFFHeader.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/TIFFStrip.cs b/src/Umbraco.Core/Media/Exif/TIFFStrip.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/TIFFStrip.cs
rename to src/Umbraco.Core/Media/Exif/TIFFStrip.cs
diff --git a/src/Umbraco.Infrastructure/Media/Exif/Utility.cs b/src/Umbraco.Core/Media/Exif/Utility.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/Exif/Utility.cs
rename to src/Umbraco.Core/Media/Exif/Utility.cs
diff --git a/src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs b/src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs
new file mode 100644
index 0000000000..441d2d6170
--- /dev/null
+++ b/src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs
@@ -0,0 +1,26 @@
+using System;
+using System.IO;
+using Umbraco.Web.Media.Exif;
+
+namespace Umbraco.Core.Media
+{
+ public static class ExifImageDimensionExtractor
+ {
+ public static bool TryGetDimensions(Stream stream, out int width, out int height)
+ {
+ var jpgInfo = ImageFile.FromStream(stream);
+ height = -1;
+ width = -1;
+ if (jpgInfo != null
+ && jpgInfo.Format != ImageFileFormat.Unknown
+ && jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
+ && jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
+ {
+ height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
+ width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
+ }
+
+ return height > 0 && width > 0;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Media/IImageDimensionExtractor.cs b/src/Umbraco.Core/Media/IImageDimensionExtractor.cs
new file mode 100644
index 0000000000..3da7f37393
--- /dev/null
+++ b/src/Umbraco.Core/Media/IImageDimensionExtractor.cs
@@ -0,0 +1,9 @@
+using System.IO;
+
+namespace Umbraco.Web.Media
+{
+ public interface IImageDimensionExtractor
+ {
+ public ImageSize GetDimensions(Stream stream);
+ }
+}
diff --git a/src/Umbraco.Core/Media/ImageSize.cs b/src/Umbraco.Core/Media/ImageSize.cs
new file mode 100644
index 0000000000..6d073ac196
--- /dev/null
+++ b/src/Umbraco.Core/Media/ImageSize.cs
@@ -0,0 +1,15 @@
+namespace Umbraco.Web.Media
+{
+ public struct ImageSize
+ {
+ public int Width { get; }
+ public int Height { get; }
+
+
+ public ImageSize(int width, int height)
+ {
+ Width = width;
+ Height = height;
+ }
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/JpegDetector.cs b/src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/TypeDetector/JpegDetector.cs
rename to src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs
diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/RasterizedTypeDetector.cs b/src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/TypeDetector/RasterizedTypeDetector.cs
rename to src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs
diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/SvgDetector.cs b/src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/TypeDetector/SvgDetector.cs
rename to src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs
diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/TIFFDetector.cs b/src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/TypeDetector/TIFFDetector.cs
rename to src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs
diff --git a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs b/src/Umbraco.Core/Media/UploadAutoFillProperties.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs
rename to src/Umbraco.Core/Media/UploadAutoFillProperties.cs
index deeed7a07c..44d5f5c8c3 100644
--- a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs
+++ b/src/Umbraco.Core/Media/UploadAutoFillProperties.cs
@@ -1,5 +1,4 @@
using System;
-using System.Drawing;
using System.IO;
using Microsoft.Extensions.Logging;
using Umbraco.Core;
@@ -18,15 +17,18 @@ namespace Umbraco.Web.Media
private readonly IMediaFileSystem _mediaFileSystem;
private readonly ILogger _logger;
private readonly IImageUrlGenerator _imageUrlGenerator;
+ private readonly IImageDimensionExtractor _imageDimensionExtractor;
public UploadAutoFillProperties(
IMediaFileSystem mediaFileSystem,
ILogger logger,
- IImageUrlGenerator imageUrlGenerator)
+ IImageUrlGenerator imageUrlGenerator,
+ IImageDimensionExtractor imageDimensionExtractor)
{
_mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_imageUrlGenerator = imageUrlGenerator ?? throw new ArgumentNullException(nameof(imageUrlGenerator));
+ _imageDimensionExtractor = imageDimensionExtractor ?? throw new ArgumentNullException(nameof(imageDimensionExtractor));
}
///
@@ -71,7 +73,7 @@ namespace Umbraco.Web.Media
using (var filestream = _mediaFileSystem.OpenFile(filepath))
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
- var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null;
+ var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (ImageSize?)_imageDimensionExtractor.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment);
}
}
@@ -105,12 +107,12 @@ namespace Umbraco.Web.Media
else
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
- var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null;
+ var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (ImageSize?)_imageDimensionExtractor.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment);
}
}
- private static void SetProperties(IContentBase content, ImagingAutoFillUploadField autoFillConfig, Size? size, long length, string extension, string culture, string segment)
+ private static void SetProperties(IContentBase content, ImagingAutoFillUploadField autoFillConfig, ImageSize? size, long length, string extension, string culture, string segment)
{
if (content == null) throw new ArgumentNullException(nameof(content));
if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs b/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs
index 6689e133fc..5f5bc3cebd 100644
--- a/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs
+++ b/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs
@@ -91,6 +91,7 @@ namespace Umbraco.Web.Models.ContentEditing
private IEnumerable _properties;
+ [DataMember(Name = "properties")]
public virtual IEnumerable Properties
{
get => _properties;
diff --git a/src/Umbraco.Core/Models/IContentModel.cs b/src/Umbraco.Core/Models/IContentModel.cs
index d0d4f175d7..692547aa3e 100644
--- a/src/Umbraco.Core/Models/IContentModel.cs
+++ b/src/Umbraco.Core/Models/IContentModel.cs
@@ -1,10 +1,30 @@
-using Umbraco.Core.Models;
+using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Web.Models
{
+ ///
+ /// The basic view model returned for front-end Umbraco controllers
+ ///
+ ///
+ ///
+ /// exists in order to unify all view models in Umbraco, whether it's a normal template view or a partial view macro, or
+ /// a user's custom model that they have created when doing route hijacking or custom routes.
+ ///
+ ///
+ /// By default all front-end template views inherit from UmbracoViewPage which has a model of but the model returned
+ /// from the controllers is which in normal circumstances would not work. This works with UmbracoViewPage because it
+ /// performs model binding between IContentModel and IPublishedContent. This offers a lot of flexibility when rendering views. In some cases if you
+ /// are route hijacking and returning a custom implementation of and your view is strongly typed to this model, you can still
+ /// render partial views created in the back office that have the default model of IPublishedContent without having to worry about explicitly passing
+ /// that model to the view.
+ ///
+ ///
public interface IContentModel
{
+ ///
+ /// Gets the
+ ///
IPublishedContent Content { get; }
}
}
diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs
index be514eaf44..cf48d6ac53 100644
--- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs
+++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Xml.Linq;
namespace Umbraco.Core.Models.Packaging
@@ -40,6 +39,8 @@ namespace Umbraco.Core.Models.Packaging
public IEnumerable Languages { get; set; } // TODO: make strongly typed
public IEnumerable DictionaryItems { get; set; } // TODO: make strongly typed
public IEnumerable DocumentTypes { get; set; } // TODO: make strongly typed
- public IEnumerable Documents { get; set; }
+ public IEnumerable MediaTypes { get; set; } // TODO: make strongly typed
+ public IEnumerable Documents { get; set; }
+ public IEnumerable Media { get; set; }
}
}
diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs
similarity index 52%
rename from src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs
rename to src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs
index c41966dfe1..7b668796a4 100644
--- a/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs
+++ b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs
@@ -1,20 +1,18 @@
-using System;
using System.Xml.Linq;
namespace Umbraco.Core.Models.Packaging
{
- public class CompiledPackageDocument
+ ///
+ /// Compiled representation of a content base (Document or Media)
+ ///
+ public class CompiledPackageContentBase
{
- public static CompiledPackageDocument Create(XElement xml)
- {
- if (xml.Name.LocalName != "DocumentSet")
- throw new ArgumentException("The xml isn't formatted correctly, a document element is defined by ", nameof(xml));
- return new CompiledPackageDocument
+ public static CompiledPackageContentBase Create(XElement xml) =>
+ new CompiledPackageContentBase
{
XmlData = xml,
ImportMode = xml.AttributeValue("importMode")
};
- }
public string ImportMode { get; set; } //this is never used
@@ -23,4 +21,4 @@ namespace Umbraco.Core.Models.Packaging
///
public XElement XmlData { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs
index cfc789324a..f9330176aa 100644
--- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Umbraco.Core.Models.PublishedContent
@@ -8,21 +8,13 @@ namespace Umbraco.Core.Models.PublishedContent
///
/// Instances implementing the interface should be
/// immutable, ie if the content type changes, then a new instance needs to be created.
- public interface IPublishedContentType2 : IPublishedContentType
+ public interface IPublishedContentType
{
///
/// Gets the unique key for the content type.
///
Guid Key { get; }
- }
- ///
- /// Represents an type.
- ///
- /// Instances implementing the interface should be
- /// immutable, ie if the content type changes, then a new instance needs to be created.
- public interface IPublishedContentType
- {
///
/// Gets the content type identifier.
///
diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs
index 14c26442eb..daf75f5c50 100644
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.PublishedContent
///
/// Instances of the class are immutable, ie
/// if the content type changes, then a new class needs to be created.
- public class PublishedContentType : IPublishedContentType2
+ public class PublishedContentType : IPublishedContentType
{
private readonly IPublishedPropertyType[] _propertyTypes;
diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeExtensions.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeExtensions.cs
deleted file mode 100644
index feab33c1d6..0000000000
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeExtensions.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-
-namespace Umbraco.Core.Models.PublishedContent
-{
- public static class PublishedContentTypeExtensions
- {
- ///
- /// Get the GUID key from an
- ///
- ///
- ///
- ///
- public static bool TryGetKey(this IPublishedContentType publishedContentType, out Guid key)
- {
- if (publishedContentType is IPublishedContentType2 contentTypeWithKey)
- {
- key = contentTypeWithKey.Key;
- return true;
- }
- key = Guid.Empty;
- return false;
- }
- }
-}
diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs
index b4cd2bd03f..be3f38cb22 100644
--- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs
+++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs
@@ -6,7 +6,6 @@ using System.Xml.Linq;
using Microsoft.Extensions.Options;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Models.Packaging;
-using File = System.IO.File;
namespace Umbraco.Core.Packaging
{
@@ -64,7 +63,9 @@ namespace Umbraco.Core.Packaging
Languages = xml.Root.Element("Languages")?.Elements("Language") ?? Enumerable.Empty(),
DictionaryItems = xml.Root.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty(),
DocumentTypes = xml.Root.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty(),
- Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageDocument.Create) ?? Enumerable.Empty(),
+ MediaTypes = xml.Root.Element("MediaTypes")?.Elements("MediaType") ?? Enumerable.Empty(),
+ Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageContentBase.Create) ?? Enumerable.Empty(),
+ Media = xml.Root.Element("MediaItems")?.Elements()?.Select(CompiledPackageContentBase.Create) ?? Enumerable.Empty(),
};
def.Warnings = GetPreInstallWarnings(def, applicationRootFolder);
diff --git a/src/Umbraco.Core/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Packaging/InstallationSummary.cs
index 1cab17e220..abeaa82bc1 100644
--- a/src/Umbraco.Core/Packaging/InstallationSummary.cs
+++ b/src/Umbraco.Core/Packaging/InstallationSummary.cs
@@ -17,11 +17,13 @@ namespace Umbraco.Core.Models.Packaging
public IEnumerable FilesInstalled { get; set; } = Enumerable.Empty();
public IEnumerable TemplatesInstalled { get; set; } = Enumerable.Empty();
public IEnumerable DocumentTypesInstalled { get; set; } = Enumerable.Empty();
+ public IEnumerable MediaTypesInstalled { get; set; } = Enumerable.Empty();
public IEnumerable StylesheetsInstalled { get; set; } = Enumerable.Empty();
public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty();
+ public IEnumerable MediaInstalled { get; set; } = Enumerable.Empty();
public IEnumerable Actions { get; set; } = Enumerable.Empty();
public IEnumerable ActionErrors { get; set; } = Enumerable.Empty();
-
+
}
}
diff --git a/src/Umbraco.Core/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Packaging/PackageDefinition.cs
index 29a1919a2b..379b400e75 100644
--- a/src/Umbraco.Core/Packaging/PackageDefinition.cs
+++ b/src/Umbraco.Core/Packaging/PackageDefinition.cs
@@ -4,7 +4,6 @@ using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
-using Umbraco.Core.Composing;
namespace Umbraco.Core.Models.Packaging
{
@@ -114,6 +113,9 @@ namespace Umbraco.Core.Models.Packaging
[DataMember(Name = "documentTypes")]
public IList DocumentTypes { get; set; } = new List();
+ [DataMember(Name = "mediaTypes")]
+ public IList MediaTypes { get; set; } = new List();
+
[DataMember(Name = "stylesheets")]
public IList Stylesheets { get; set; } = new List();
@@ -133,6 +135,12 @@ namespace Umbraco.Core.Models.Packaging
[DataMember(Name = "iconUrl")]
public string IconUrl { get; set; } = string.Empty;
+ [DataMember(Name = "mediaUdis")]
+ public IList MediaUdis { get; set; } = Array.Empty();
+
+ [DataMember(Name = "mediaLoadChildNodes")]
+ public bool MediaLoadChildNodes { get; set; }
+
}
diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs
index a9516d7e25..d194b0ea56 100644
--- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs
+++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs
@@ -46,10 +46,13 @@ namespace Umbraco.Core.Packaging
Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value
ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty,
ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false,
+ MediaUdis = xml.Element("media")?.Elements("nodeUdi").Select(x => (GuidUdi)UdiParser.Parse(x.Value)).ToList() ?? new List(),
+ MediaLoadChildNodes = xml.Element("media")?.AttributeValue("loadChildNodes") ?? false,
Macros = xml.Element("macros")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
Templates = xml.Element("templates")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
+ MediaTypes = xml.Element("mediaTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
Languages = xml.Element("languages")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(),
@@ -103,11 +106,17 @@ namespace Umbraco.Core.Packaging
new XElement("templates", string.Join(",", def.Templates ?? Array.Empty())),
new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty())),
new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty())),
+ new XElement("mediaTypes", string.Join(",", def.MediaTypes ?? Array.Empty())),
new XElement("macros", string.Join(",", def.Macros ?? Array.Empty())),
new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))),
new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())),
- new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())));
+ new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())),
+ new XElement(
+ "media",
+ def.MediaUdis.Select(x=> (object)new XElement("nodeUdi", x))
+ .Union(new []{new XAttribute("loadChildNodes", def.MediaLoadChildNodes) }))
+ );
return packageXml;
}
diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs
index 59741ab1ce..b89448d891 100644
--- a/src/Umbraco.Core/Packaging/PackagesRepository.cs
+++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs
@@ -5,8 +5,8 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Xml.Linq;
-using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
@@ -38,6 +38,8 @@ namespace Umbraco.Core.Packaging
private readonly string _tempFolderPath;
private readonly PackageDefinitionXmlParser _parser;
private readonly IUmbracoVersion _umbracoVersion;
+ private readonly IMediaService _mediaService;
+ private readonly IMediaTypeService _mediaTypeService;
///
/// Constructor
@@ -65,6 +67,8 @@ namespace Umbraco.Core.Packaging
ILoggerFactory loggerFactory,
IUmbracoVersion umbracoVersion,
IOptions globalSettings,
+ IMediaService mediaService,
+ IMediaTypeService mediaTypeService,
string packageRepositoryFileName,
string tempFolderPath = null, string packagesFolderPath = null, string mediaFolderPath = null)
{
@@ -87,6 +91,8 @@ namespace Umbraco.Core.Packaging
_parser = new PackageDefinitionXmlParser(_loggerFactory.CreateLogger(), umbracoVersion);
_umbracoVersion = umbracoVersion;
+ _mediaService = mediaService;
+ _mediaTypeService = mediaTypeService;
}
private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + _packageRepositoryFileName;
@@ -181,12 +187,15 @@ namespace Umbraco.Core.Packaging
PackageDocumentsAndTags(definition, root);
PackageDocumentTypes(definition, root);
+ PackageMediaTypes(definition, root);
PackageTemplates(definition, root);
PackageStylesheets(definition, root);
PackageMacros(definition, root, filesXml, temporaryPath);
PackageDictionaryItems(definition, root);
PackageLanguages(definition, root);
PackageDataTypes(definition, root);
+ PackageMedia(definition, root);
+
// TODO: This needs to be split into content vs web files, for now we are going to
// assume all files are web (www) files. But this is a larger discussion/change since
@@ -194,13 +203,13 @@ namespace Umbraco.Core.Packaging
//Files
foreach (var fileName in definition.Files)
- AppendFileToPackage(fileName, temporaryPath, filesXml, true);
+ AppendFileToPackage(fileName, temporaryPath, filesXml);
//Load view on install...
if (!string.IsNullOrEmpty(definition.PackageView))
{
var control = new XElement("view", definition.PackageView);
- AppendFileToPackage(definition.PackageView, temporaryPath, filesXml, true);
+ AppendFileToPackage(definition.PackageView, temporaryPath, filesXml);
root.Add(control);
}
@@ -310,7 +319,7 @@ namespace Umbraco.Core.Packaging
macros.Add(macroXml);
//if the macro has a file copy it to the xml
if (!string.IsNullOrEmpty(macro.MacroSource))
- AppendFileToPackage(macro.MacroSource, temporaryPath, filesXml, false);
+ AppendFileToPackage(macro.MacroSource, temporaryPath, filesXml);
}
root.Add(macros);
}
@@ -358,6 +367,23 @@ namespace Umbraco.Core.Packaging
root.Add(docTypesXml);
}
+ private void PackageMediaTypes(PackageDefinition definition, XContainer root)
+ {
+ var mediaTypes = new HashSet();
+ var mediaTypesXml = new XElement("MediaTypes");
+ foreach (var mediaTypeId in definition.MediaTypes)
+ {
+ if (!int.TryParse(mediaTypeId, out var outInt)) continue;
+ var mediaType = _mediaTypeService.Get(outInt);
+ if (mediaType == null) continue;
+ AddMediaType(mediaType, mediaTypes);
+ }
+ foreach (var mediaType in mediaTypes)
+ mediaTypesXml.Add(_serializer.Serialize(mediaType));
+
+ root.Add(mediaTypesXml);
+ }
+
private void PackageDocumentsAndTags(PackageDefinition definition, XContainer root)
{
//Documents and tags
@@ -442,6 +468,18 @@ namespace Umbraco.Core.Packaging
}
}
+
+ private void PackageMedia(PackageDefinition definition, XElement root)
+ {
+ IEnumerable medias = _mediaService.GetByIds(definition.MediaUdis);
+
+ root.Add(
+ new XElement(
+ "MediaItems",
+ medias.Select(x => new XElement("MediaSet", _serializer.Serialize(x, definition.MediaLoadChildNodes)))));
+ }
+
+
///
/// Zips the package.
///
@@ -461,12 +499,12 @@ namespace Umbraco.Core.Packaging
/// The package directory.
/// The files xml node
/// true if it's a web file, false if it's a content file
- private void AppendFileToPackage(string path, string packageDirectory, XContainer filesXml, bool isWebFile)
+ private void AppendFileToPackage(string path, string packageDirectory, XContainer filesXml)
{
if (!path.StartsWith("~/") && !path.StartsWith("/"))
path = "~/" + path;
- var serverPath = isWebFile ? _hostingEnvironment.MapPathWebRoot(path) : _hostingEnvironment.MapPathContentRoot(path);
+ var serverPath = _hostingEnvironment.MapPathContentRoot(path);
if (File.Exists(serverPath))
AppendFileXml(new FileInfo(serverPath), path, packageDirectory, filesXml);
@@ -562,6 +600,19 @@ namespace Umbraco.Core.Packaging
dtl.Add(dt);
}
+ private void AddMediaType(IMediaType mediaType, HashSet mediaTypes)
+ {
+ if (mediaType.ParentId > 0)
+ {
+ var parent = _mediaTypeService.Get(mediaType.ParentId);
+ if (parent != null) // could be a container
+ AddMediaType(parent, mediaTypes);
+ }
+
+ if (!mediaTypes.Contains(mediaType))
+ mediaTypes.Add(mediaType);
+ }
+
private static XElement GetPackageInfoXml(PackageDefinition definition, IUmbracoVersion umbracoVersion)
{
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfiguration.cs b/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs
similarity index 76%
rename from src/Umbraco.Infrastructure/PropertyEditors/BlockListConfiguration.cs
rename to src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs
index 1af3aa1303..f0aa1f0b77 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfiguration.cs
+++ b/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs
@@ -1,5 +1,5 @@
-using Newtonsoft.Json;
-using System;
+using System;
+using System.Runtime.Serialization;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
@@ -12,37 +12,38 @@ namespace Umbraco.Web.PropertyEditors
[ConfigurationField("blocks", "Available Blocks", "views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html", Description = "Define the available blocks.")]
public BlockConfiguration[] Blocks { get; set; }
+ [DataContract]
public class BlockConfiguration
{
- [JsonProperty("backgroundColor")]
+ [DataMember(Name ="backgroundColor")]
public string BackgroundColor { get; set; }
- [JsonProperty("iconColor")]
+ [DataMember(Name ="iconColor")]
public string IconColor { get; set; }
- [JsonProperty("thumbnail")]
+ [DataMember(Name ="thumbnail")]
public string Thumbnail { get; set; }
- [JsonProperty("contentElementTypeKey")]
+ [DataMember(Name ="contentElementTypeKey")]
public Guid ContentElementTypeKey { get; set; }
- [JsonProperty("settingsElementTypeKey")]
+ [DataMember(Name ="settingsElementTypeKey")]
public Guid? SettingsElementTypeKey { get; set; }
- [JsonProperty("view")]
+ [DataMember(Name ="view")]
public string View { get; set; }
- [JsonProperty("stylesheet")]
+ [DataMember(Name ="stylesheet")]
public string Stylesheet { get; set; }
- [JsonProperty("label")]
+ [DataMember(Name ="label")]
public string Label { get; set; }
- [JsonProperty("editorSize")]
+ [DataMember(Name ="editorSize")]
public string EditorSize { get; set; }
- [JsonProperty("forceHideContentEditorInOverlay")]
+ [DataMember(Name ="forceHideContentEditorInOverlay")]
public bool ForceHideContentEditorInOverlay { get; set; }
}
@@ -51,10 +52,10 @@ namespace Umbraco.Web.PropertyEditors
public class NumberRange
{
- [JsonProperty("min")]
+ [DataMember(Name ="min")]
public int? Min { get; set; }
- [JsonProperty("max")]
+ [DataMember(Name ="max")]
public int? Max { get; set; }
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs b/src/Umbraco.Core/PropertyEditors/DataEditor.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs
rename to src/Umbraco.Core/PropertyEditors/DataEditor.cs
index d74f285553..ef533aa083 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/DataEditor.cs
@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Runtime.Serialization;
using Microsoft.Extensions.Logging;
using Umbraco.Core.Composing;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -26,13 +27,21 @@ namespace Umbraco.Core.PropertyEditors
///
/// Initializes a new instance of the class.
///
- public DataEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, EditorType type = EditorType.PropertyValue)
+ public DataEditor(
+ ILoggerFactory loggerFactory,
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer,
+ EditorType type = EditorType.PropertyValue)
{
LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
DataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService));
LocalizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
LocalizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService));
ShortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper));
+ JsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer));
// defaults
@@ -58,6 +67,7 @@ namespace Umbraco.Core.PropertyEditors
protected DataEditorAttribute Attribute { get; }
protected IShortStringHelper ShortStringHelper { get; }
+ public IJsonSerializer JsonSerializer { get; }
protected ILocalizedTextService LocalizedTextService { get; }
protected ILocalizationService LocalizationService { get; }
protected ILoggerFactory LoggerFactory { get; }
@@ -65,7 +75,7 @@ namespace Umbraco.Core.PropertyEditors
///
[DataMember(Name = "alias", IsRequired = true)]
- public string Alias { get; internal set; }
+ public string Alias { get; set; }
///
[IgnoreDataMember]
@@ -174,7 +184,7 @@ namespace Umbraco.Core.PropertyEditors
if (Attribute == null)
throw new InvalidOperationException($"The editor is not attributed with {nameof(DataEditorAttribute)}");
- return new DataValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute);
+ return new DataValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer, Attribute);
}
///
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs
similarity index 93%
rename from src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs
rename to src/Umbraco.Core/PropertyEditors/DataValueEditor.cs
index fec245009f..237af042cf 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs
@@ -3,14 +3,13 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
+using System.Runtime.Serialization;
using System.Xml.Linq;
using Microsoft.Extensions.Logging;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.PropertyEditors.Validators;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -19,20 +18,28 @@ namespace Umbraco.Core.PropertyEditors
///
/// Represents a value editor.
///
+ [DataContract]
public class DataValueEditor : IDataValueEditor
{
private readonly ILocalizedTextService _localizedTextService;
private readonly IShortStringHelper _shortStringHelper;
+ private readonly IJsonSerializer _jsonSerializer;
protected IDataTypeService DataTypeService { get; }
protected ILocalizationService LocalizationService { get; }
///
/// Initializes a new instance of the class.
///
- public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) // for tests, and manifest
+ public DataValueEditor(
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer) // for tests, and manifest
{
_localizedTextService = localizedTextService;
_shortStringHelper = shortStringHelper;
+ _jsonSerializer = jsonSerializer;
ValueType = ValueTypes.String;
Validators = new List();
DataTypeService = dataTypeService;
@@ -42,11 +49,18 @@ namespace Umbraco.Core.PropertyEditors
///
/// Initializes a new instance of the class.
///
- public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute)
+ public DataValueEditor(
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer,
+ DataEditorAttribute attribute)
{
if (attribute == null) throw new ArgumentNullException(nameof(attribute));
_localizedTextService = localizedTextService;
_shortStringHelper = shortStringHelper;
+ _jsonSerializer = jsonSerializer;
var view = attribute.View;
if (string.IsNullOrWhiteSpace(view))
@@ -72,13 +86,14 @@ namespace Umbraco.Core.PropertyEditors
/// The view can be three things: (1) the full virtual path, or (2) the relative path to the current Umbraco
/// folder, or (3) a view name which maps to views/propertyeditors/{view}/{view}.html.
///
- [JsonProperty("view", Required = Required.Always)]
+ [Required]
+ [DataMember(Name = "view")]
public string View { get; set; }
///
/// The value type which reflects how it is validated and stored in the database
///
- [JsonProperty("valueType")]
+ [DataMember(Name = "valueType")]
public string ValueType { get; set; }
///
@@ -111,7 +126,7 @@ namespace Umbraco.Core.PropertyEditors
///
/// A collection of validators for the pre value editor
///
- [JsonProperty("validation")]
+ [DataMember(Name = "validation")]
public List Validators { get; private set; } = new List();
///
@@ -127,7 +142,7 @@ namespace Umbraco.Core.PropertyEditors
///
/// If this is true than the editor will be displayed full width without a label
///
- [JsonProperty("hideLabel")]
+ [DataMember(Name = "hideLabel")]
public bool HideLabel { get; set; }
///
@@ -142,8 +157,8 @@ namespace Umbraco.Core.PropertyEditors
///
internal Attempt
internal class DateValueEditor : DataValueEditor
{
- public DateValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute)
- : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute)
+ public DateValueEditor(
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer,
+ DataEditorAttribute attribute)
+ : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute)
{
Validators.Add(new DateTimeValidator());
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DecimalPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/DecimalPropertyEditor.cs
similarity index 88%
rename from src/Umbraco.Infrastructure/PropertyEditors/DecimalPropertyEditor.cs
rename to src/Umbraco.Core/PropertyEditors/DecimalPropertyEditor.cs
index 8d2280b23b..4aea9f944f 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/DecimalPropertyEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/DecimalPropertyEditor.cs
@@ -2,6 +2,7 @@
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.Validators;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -26,8 +27,9 @@ namespace Umbraco.Web.PropertyEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{ }
///
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/IntegerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/IntegerPropertyEditor.cs
similarity index 72%
rename from src/Umbraco.Infrastructure/PropertyEditors/IntegerPropertyEditor.cs
rename to src/Umbraco.Core/PropertyEditors/IntegerPropertyEditor.cs
index 417ec112d7..43b988a49f 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/IntegerPropertyEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/IntegerPropertyEditor.cs
@@ -2,6 +2,7 @@
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.Validators;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -18,8 +19,14 @@ namespace Umbraco.Web.PropertyEditors
ValueType = ValueTypes.Integer)]
public class IntegerPropertyEditor : DataEditor
{
- public IntegerPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService)
- : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper)
+ public IntegerPropertyEditor(
+ ILoggerFactory loggerFactory,
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ IShortStringHelper shortStringHelper,
+ ILocalizedTextService localizedTextService,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer)
{ }
///
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MemberGroupPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs
similarity index 81%
rename from src/Umbraco.Infrastructure/PropertyEditors/MemberGroupPickerPropertyEditor.cs
rename to src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs
index eb50d02284..34448b3816 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/MemberGroupPickerPropertyEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -20,8 +21,9 @@ namespace Umbraco.Web.PropertyEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{ }
}
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs
similarity index 83%
rename from src/Umbraco.Infrastructure/PropertyEditors/MemberPickerPropertyEditor.cs
rename to src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs
index 3676340aee..b572f47cfd 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/MemberPickerPropertyEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -20,8 +21,9 @@ namespace Umbraco.Web.PropertyEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{ }
protected override IConfigurationEditor CreateConfigurationEditor() => new MemberPickerConfiguration();
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs
similarity index 85%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs
index 2da9e184c3..619fd89692 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -23,8 +24,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiple", false);
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs
similarity index 86%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs
index d416cf111a..5110dfdc79 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -24,8 +25,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiPicker", "1");
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs
similarity index 82%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs
index 613d6a6a5e..ff08420cd9 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiple", true);
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs
similarity index 81%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs
index 73a3b42610..a2750447a8 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs
@@ -1,6 +1,7 @@
-using Umbraco.Core;
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging;
+using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -25,8 +26,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
DefaultConfiguration.Add("multiPicker", "1");
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs
similarity index 84%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs
index 16cd596fc8..22571db975 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiple", true);
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs
similarity index 84%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs
index e9576fab02..251d982777 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiple", "1");
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs
similarity index 84%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs
index 345afa3b46..aabef3e1b0 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiple", "0");
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs
similarity index 83%
rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs
rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs
index be682a35d3..c3178d3138 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
// configure
DefaultConfiguration.Add("multiple", "0");
diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs
index 2149ece02a..a3c02aeb0d 100644
--- a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs
+++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs
@@ -1,11 +1,9 @@
-using System.Linq;
+using System.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.Manifest;
namespace Umbraco.Core.PropertyEditors
{
-
-
public class PropertyEditorCollection : BuilderCollectionBase
{
public PropertyEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser)
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfiguration.cs b/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/PropertyEditors/RichTextConfiguration.cs
rename to src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs
index c6d4e3ce70..c1fb61bde8 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfiguration.cs
+++ b/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs
@@ -1,5 +1,4 @@
-using Newtonsoft.Json.Linq;
-using Umbraco.Core;
+using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
@@ -11,7 +10,7 @@ namespace Umbraco.Web.PropertyEditors
{
// TODO: Make these strongly typed, for now this works though
[ConfigurationField("editor", "Editor", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
- public JObject Editor { get; set; }
+ public object Editor { get; set; }
[ConfigurationField("hideLabel", "Hide Label", "boolean")]
public bool HideLabel { get; set; }
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextOnlyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs
similarity index 80%
rename from src/Umbraco.Infrastructure/PropertyEditors/TextOnlyValueEditor.cs
rename to src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs
index ec48cf8b57..aeac87079c 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/TextOnlyValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -12,8 +13,14 @@ namespace Umbraco.Web.PropertyEditors
///
public class TextOnlyValueEditor : DataValueEditor
{
- public TextOnlyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper)
- : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute)
+ public TextOnlyValueEditor(
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ DataEditorAttribute attribute,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute)
{ }
///
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs
rename to src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs
similarity index 82%
rename from src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs
rename to src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs
index 891fb54ee3..f22c3d94dc 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -20,8 +21,9 @@ namespace Umbraco.Web.PropertyEditors
IDataTypeService dataTypeService,
ILocalizationService localizationService,
ILocalizedTextService localizedTextService,
- IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{ }
protected override IConfigurationEditor CreateConfigurationEditor() => new UserPickerConfiguration();
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs
rename to src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs
rename to src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorValidationResult.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorValidationResult.cs
rename to src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorValidationResult.cs
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs
rename to src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs
similarity index 95%
rename from src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs
rename to src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs
index 51471f6da7..64ecba5c7c 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Strings;
@@ -8,7 +8,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
/// Value converter for the RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used.
///
[DefaultPropertyValueConverter]
- public class TinyMceValueConverter : PropertyValueConverterBase
+ public class SimpleTinyMceValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias == Constants.PropertyEditors.Aliases.TinyMce;
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs
deleted file mode 100644
index 7caa9a90cc..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Linq;
-using Umbraco.Core.Models.PublishedContent;
-
-namespace Umbraco.Core.PropertyEditors.ValueConverters
-{
- [DefaultPropertyValueConverter]
- public class TextStringValueConverter : PropertyValueConverterBase
- {
- private static readonly string[] PropertyTypeAliases =
- {
- Constants.PropertyEditors.Aliases.TextBox,
- Constants.PropertyEditors.Aliases.TextArea
- };
-
- public override bool IsConverter(IPublishedPropertyType propertyType)
- => PropertyTypeAliases.Contains(propertyType.EditorAlias);
-
- public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
- => typeof (string);
-
- public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
- => PropertyCacheLevel.Element;
-
- public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
- {
- // in xml a string is: string
- // in the database a string is: string
- // default value is: null
- return source;
- }
-
- public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
- {
- // source should come from ConvertSource and be a string (or null) already
- return inter ?? string.Empty;
- }
-
- public override object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
- {
- // source should come from ConvertSource and be a string (or null) already
- return inter;
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/VoidEditor.cs b/src/Umbraco.Core/PropertyEditors/VoidEditor.cs
similarity index 73%
rename from src/Umbraco.Infrastructure/PropertyEditors/VoidEditor.cs
rename to src/Umbraco.Core/PropertyEditors/VoidEditor.cs
index e26cd4129a..d2e84b7952 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/VoidEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/VoidEditor.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Umbraco.Core.Composing;
+using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
@@ -14,6 +15,8 @@ namespace Umbraco.Core.PropertyEditors
[HideFromTypeFinder]
public class VoidEditor : DataEditor
{
+ private readonly IJsonSerializer _jsonSerializer;
+
///
/// Initializes a new instance of the class.
///
@@ -21,8 +24,15 @@ namespace Umbraco.Core.PropertyEditors
/// A logger factory.
/// The default alias of the editor is "Umbraco.Void". When a suffix is provided,
/// it is appended to the alias. Eg if the suffix is "Foo" the alias is "Umbraco.Void.Foo".
- public VoidEditor(string aliasSuffix, ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper)
- : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ public VoidEditor(
+ string aliasSuffix,
+ ILoggerFactory loggerFactory,
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer)
+ : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{
Alias = "Umbraco.Void";
if (string.IsNullOrWhiteSpace(aliasSuffix)) return;
@@ -34,8 +44,8 @@ namespace Umbraco.Core.PropertyEditors
///
/// A logger factory.
/// The alias of the editor is "Umbraco.Void".
- public VoidEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper)
- : this(null, loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper)
+ public VoidEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer)
+ : this(null, loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer)
{ }
}
}
diff --git a/src/Umbraco.Core/PublishedCache/IPublishedSnapshotService.cs b/src/Umbraco.Core/PublishedCache/IPublishedSnapshotService.cs
index 68b2367ce0..7307ba97f9 100644
--- a/src/Umbraco.Core/PublishedCache/IPublishedSnapshotService.cs
+++ b/src/Umbraco.Core/PublishedCache/IPublishedSnapshotService.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using Umbraco.Core.Models.Membership;
+using System.Threading.Tasks;
using Umbraco.Web.Cache;
namespace Umbraco.Web.PublishedCache
@@ -11,8 +11,6 @@ namespace Umbraco.Web.PublishedCache
///
public interface IPublishedSnapshotService : IDisposable
{
- #region PublishedSnapshot
-
/* Various places (such as Node) want to access the XML content, today as an XmlDocument
* but to migrate to a new cache, they're migrating to an XPathNavigator. Still, they need
* to find out how to get that navigator.
@@ -36,85 +34,23 @@ namespace Umbraco.Web.PublishedCache
IPublishedSnapshot CreatePublishedSnapshot(string previewToken);
///
- /// Gets the published snapshot accessor.
- ///
- IPublishedSnapshotAccessor PublishedSnapshotAccessor { get; }
-
- ///
- /// Ensures that the published snapshot has the proper environment to run.
- ///
- /// The errors, if any.
- /// A value indicating whether the published snapshot has the proper environment to run.
- bool EnsureEnvironment(out IEnumerable errors);
-
- #endregion
-
- #region Rebuild
-
- ///
- /// Rebuilds internal caches (but does not reload).
+ /// Rebuilds internal database caches (but does not reload).
///
+ /// The operation batch size to process the items
+ /// If not null will process content for the matching content types, if empty will process all content
+ /// If not null will process content for the matching media types, if empty will process all media
+ /// If not null will process content for the matching members types, if empty will process all members
///
- /// Forces the snapshot service to rebuild its internal caches. For instance, some caches
+ /// Forces the snapshot service to rebuild its internal database caches. For instance, some caches
/// may rely on a database table to store pre-serialized version of documents.
/// This does *not* reload the caches. Caches need to be reloaded, for instance via
/// RefreshAllPublishedSnapshot method.
///
- void Rebuild();
-
- #endregion
-
- #region Preview
-
- /* Later on we can imagine that EnterPreview would handle a "level" that would be either
- * the content only, or the content's branch, or the whole tree + it could be possible
- * to register filters against the factory to filter out which nodes should be preview
- * vs non preview.
- *
- * EnterPreview() returns the previewToken. It is up to callers to store that token
- * wherever they want, most probably in a cookie.
- *
- */
-
- ///
- /// Enters preview for specified user and content.
- ///
- /// The user.
- /// The content identifier.
- /// A preview token.
- ///
- /// Tells the caches that they should prepare any data that they would be keeping
- /// in order to provide preview to a give user. In the Xml cache this means creating the Xml
- /// file, though other caches may do things differently.
- /// Does not handle the preview token storage (cookie, etc) that must be handled separately.
- ///
- string EnterPreview(IUser user, int contentId);
-
- ///
- /// Refreshes preview for a specified content.
- ///
- /// The preview token.
- /// The content identifier.
- /// Tells the caches that they should update any data that they would be keeping
- /// in order to provide preview to a given user. In the Xml cache this means updating the Xml
- /// file, though other caches may do things differently.
- void RefreshPreview(string previewToken, int contentId);
-
- ///
- /// Exits preview for a specified preview token.
- ///
- /// The preview token.
- ///
- /// Tells the caches that they can dispose of any data that they would be keeping
- /// in order to provide preview to a given user. In the Xml cache this means deleting the Xml file,
- /// though other caches may do things differently.
- /// Does not handle the preview token storage (cookie, etc) that must be handled separately.
- ///
- void ExitPreview(string previewToken);
-
- #endregion
-
- #region Changes
+ void Rebuild(
+ int groupSize = 5000,
+ IReadOnlyCollection contentTypeIds = null,
+ IReadOnlyCollection mediaTypeIds = null,
+ IReadOnlyCollection memberTypeIds = null);
/* An IPublishedCachesService implementation can rely on transaction-level events to update
* its internal, database-level data, as these events are purely internal. However, it cannot
@@ -160,16 +96,9 @@ namespace Umbraco.Web.PublishedCache
/// The changes.
void Notify(DomainCacheRefresher.JsonPayload[] payloads);
- #endregion
-
- #region Status
-
- string GetStatus();
-
- string StatusUrl { get; }
-
- #endregion
-
- void Collect();
+ ///
+ /// Cleans up unused snapshots
+ ///
+ Task CollectAsync();
}
}
diff --git a/src/Umbraco.Core/PublishedCache/IPublishedSnapshotStatus.cs b/src/Umbraco.Core/PublishedCache/IPublishedSnapshotStatus.cs
new file mode 100644
index 0000000000..0f88bd4085
--- /dev/null
+++ b/src/Umbraco.Core/PublishedCache/IPublishedSnapshotStatus.cs
@@ -0,0 +1,18 @@
+namespace Umbraco.Web.PublishedCache
+{
+ ///
+ /// Returns the currents status for nucache
+ ///
+ public interface IPublishedSnapshotStatus
+ {
+ ///
+ /// Gets the status report as a string
+ ///
+ string GetStatus();
+
+ ///
+ /// Gets the URL used to retreive the status
+ ///
+ string StatusUrl { get; }
+ }
+}
diff --git a/src/Umbraco.Core/ITagQuery.cs b/src/Umbraco.Core/PublishedCache/ITagQuery.cs
similarity index 100%
rename from src/Umbraco.Core/ITagQuery.cs
rename to src/Umbraco.Core/PublishedCache/ITagQuery.cs
diff --git a/src/Umbraco.Core/PublishedCache/PublishedSnapshotServiceBase.cs b/src/Umbraco.Core/PublishedCache/PublishedSnapshotServiceBase.cs
deleted file mode 100644
index 9c71bdc04b..0000000000
--- a/src/Umbraco.Core/PublishedCache/PublishedSnapshotServiceBase.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Models.PublishedContent;
-using Umbraco.Web.Cache;
-
-namespace Umbraco.Web.PublishedCache
-{
- public abstract class PublishedSnapshotServiceBase : IPublishedSnapshotService
- {
- protected PublishedSnapshotServiceBase(IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
- {
- PublishedSnapshotAccessor = publishedSnapshotAccessor;
- VariationContextAccessor = variationContextAccessor;
- }
-
- public IPublishedSnapshotAccessor PublishedSnapshotAccessor { get; }
- public IVariationContextAccessor VariationContextAccessor { get; }
-
- // note: NOT setting _publishedSnapshotAccessor.PublishedSnapshot here because it is the
- // responsibility of the caller to manage what the 'current' facade is
- public abstract IPublishedSnapshot CreatePublishedSnapshot(string previewToken);
-
- protected IPublishedSnapshot CurrentPublishedSnapshot => PublishedSnapshotAccessor.PublishedSnapshot;
-
- public abstract bool EnsureEnvironment(out IEnumerable errors);
-
- public abstract string EnterPreview(IUser user, int contentId);
- public abstract void RefreshPreview(string previewToken, int contentId);
- public abstract void ExitPreview(string previewToken);
- public abstract void Notify(ContentCacheRefresher.JsonPayload[] payloads, out bool draftChanged, out bool publishedChanged);
- public abstract void Notify(MediaCacheRefresher.JsonPayload[] payloads, out bool anythingChanged);
- public abstract void Notify(ContentTypeCacheRefresher.JsonPayload[] payloads);
- public abstract void Notify(DataTypeCacheRefresher.JsonPayload[] payloads);
- public abstract void Notify(DomainCacheRefresher.JsonPayload[] payloads);
-
- public virtual void Rebuild()
- { }
-
- public virtual void Dispose()
- { }
-
- public abstract string GetStatus();
-
- public virtual string StatusUrl => "views/dashboard/settings/publishedsnapshotcache.html";
-
- public virtual void Collect()
- {
- }
- }
-}
diff --git a/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs b/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs
index 7e0ebc6f13..874da1f3aa 100644
--- a/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs
+++ b/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs
@@ -1,6 +1,11 @@
-using System;
+using System;
namespace Umbraco.Web.PublishedCache
{
+ // TODO: This is a mess. This is a circular reference:
+ // IPublishedSnapshotAccessor -> PublishedSnapshotService -> UmbracoContext -> PublishedSnapshotService -> IPublishedSnapshotAccessor
+ // Injecting IPublishedSnapshotAccessor into PublishedSnapshotService seems pretty strange
+ // The underlying reason for this mess is because IPublishedContent is both a service and a model.
+ // Until that is fixed, IPublishedContent will need to have a IPublishedSnapshotAccessor
public class UmbracoContextPublishedSnapshotAccessor : IPublishedSnapshotAccessor
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
diff --git a/src/Umbraco.Core/Routing/IPublishedRequest.cs b/src/Umbraco.Core/Routing/IPublishedRequest.cs
index f357108a4e..51fc9ccf64 100644
--- a/src/Umbraco.Core/Routing/IPublishedRequest.cs
+++ b/src/Umbraco.Core/Routing/IPublishedRequest.cs
@@ -11,7 +11,7 @@ namespace Umbraco.Web.Routing
///
/// Gets the UmbracoContext.
///
- IUmbracoContext UmbracoContext { get; }
+ IUmbracoContext UmbracoContext { get; } // TODO: This should be injected and removed from here
///
/// Gets or sets the cleaned up Uri used for routing.
diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs
index 9b7354de74..10986b941a 100644
--- a/src/Umbraco.Core/Routing/PublishedRouter.cs
+++ b/src/Umbraco.Core/Routing/PublishedRouter.cs
@@ -138,7 +138,7 @@ namespace Umbraco.Web.Routing
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = request.Culture;
SetVariationContext(request.Culture.Name);
- //find the published content if it's not assigned. This could be manually assigned with a custom route handler, or
+ // find the published content if it's not assigned. This could be manually assigned with a custom route handler, or
// with something like EnsurePublishedContentRequestAttribute or UmbracoVirtualNodeRouteHandler. Those in turn call this method
// to setup the rest of the pipeline but we don't want to run the finders since there's one assigned.
if (request.PublishedContent == null)
@@ -156,15 +156,13 @@ namespace Umbraco.Web.Routing
// trigger the Prepared event - at that point it is still possible to change about anything
// even though the request might be flagged for redirection - we'll redirect _after_ the event
- //
// also, OnPrepared() will make the PublishedRequest readonly, so nothing can change
- //
request.OnPrepared();
// we don't take care of anything so if the content has changed, it's up to the user
// to find out the appropriate template
- //complete the PCR and assign the remaining values
+ // complete the PCR and assign the remaining values
return ConfigureRequest(request);
}
@@ -201,7 +199,6 @@ namespace Umbraco.Web.Routing
// can't go beyond that point without a PublishedContent to render
// it's ok not to have a template, in order to give MVC a chance to hijack routes
-
return true;
}
diff --git a/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs b/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
new file mode 100644
index 0000000000..5f219ac51f
--- /dev/null
+++ b/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Umbraco.Core.Events;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.Manifest;
+
+namespace Umbraco.Core.Runtime
+{
+ ///
+ /// Starts monitoring AppPlugins directory during debug runs, to restart site when a plugin manifest changes.
+ ///
+ public sealed class AppPluginsManifestWatcherNotificationHandler : INotificationHandler
+ {
+ private readonly ManifestWatcher _manifestWatcher;
+ private readonly IHostingEnvironment _hostingEnvironment;
+
+ public AppPluginsManifestWatcherNotificationHandler(ManifestWatcher manifestWatcher, IHostingEnvironment hostingEnvironment)
+ {
+ _manifestWatcher = manifestWatcher ?? throw new ArgumentNullException(nameof(manifestWatcher));
+ _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
+ }
+
+ public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
+ {
+ if (!_hostingEnvironment.IsDebugMode)
+ {
+ return Task.CompletedTask;
+ }
+
+ var appPlugins = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins);
+
+ if (!Directory.Exists(appPlugins))
+ {
+ return Task.CompletedTask;
+ }
+
+ _manifestWatcher.Start(Directory.GetDirectories(appPlugins));
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs
similarity index 70%
rename from src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs
rename to src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs
index 73318208b6..92ad5808b3 100644
--- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs
+++ b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs
@@ -1,25 +1,27 @@
-using Microsoft.Extensions.Options;
-using Umbraco.Core.Composing;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Options;
using Umbraco.Core.Configuration.Models;
+using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
namespace Umbraco.Core.Runtime
{
- public class CoreInitialComponent : IComponent
+ public class EssentialDirectoryCreator : INotificationHandler
{
private readonly IIOHelper _ioHelper;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly GlobalSettings _globalSettings;
- public CoreInitialComponent(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IOptions globalSettings)
+ public EssentialDirectoryCreator(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IOptions globalSettings)
{
_ioHelper = ioHelper;
_hostingEnvironment = hostingEnvironment;
_globalSettings = globalSettings.Value;
}
- public void Initialize()
+ public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
{
// ensure we have some essential directories
// every other component can then initialize safely
@@ -28,9 +30,8 @@ namespace Umbraco.Core.Runtime
_ioHelper.EnsurePathExists(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.MvcViews));
_ioHelper.EnsurePathExists(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.PartialViews));
_ioHelper.EnsurePathExists(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.MacroPartials));
- }
- public void Terminate()
- { }
+ return Task.CompletedTask;
+ }
}
}
diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs
index c413557a27..f1f6ee3afc 100644
--- a/src/Umbraco.Core/Runtime/MainDom.cs
+++ b/src/Umbraco.Core/Runtime/MainDom.cs
@@ -157,7 +157,15 @@ namespace Umbraco.Core.Runtime
_logger.LogInformation("Acquiring.");
// Get the lock
- var acquired = _mainDomLock.AcquireLockAsync(LockTimeoutMilliseconds).GetAwaiter().GetResult();
+ var acquired = false;
+ try
+ {
+ acquired = _mainDomLock.AcquireLockAsync(LockTimeoutMilliseconds).GetAwaiter().GetResult();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error while acquiring");
+ }
if (!acquired)
{
diff --git a/src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs
rename to src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs
index eed13f5060..74dea6742c 100644
--- a/src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs
+++ b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Runtime
_logger = logger;
}
- //WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
+ // WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
public Task ListenAsync() => _signal.WaitOneAsync();
public Task AcquireLockAsync(int millisecondsTimeout)
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime
// if more than 1 instance reach that point, one will get the lock
// and the other one will timeout, which is accepted
- //This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset.
+ // This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset.
try
{
_lockRelease = _systemLock.Lock(millisecondsTimeout);
diff --git a/src/Umbraco.Core/Services/Implement/DashboardService.cs b/src/Umbraco.Core/Services/DashboardService.cs
similarity index 100%
rename from src/Umbraco.Core/Services/Implement/DashboardService.cs
rename to src/Umbraco.Core/Services/DashboardService.cs
diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs
index 25428f420b..61504b0a98 100644
--- a/src/Umbraco.Core/Services/IContentService.cs
+++ b/src/Umbraco.Core/Services/IContentService.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Querying;
@@ -10,7 +9,7 @@ namespace Umbraco.Core.Services
///
/// Defines the ContentService, which is an easy access to operations involving
///
- public interface IContentService : IContentServiceBase
+ public interface IContentService : IContentServiceBase
{
#region Blueprints
diff --git a/src/Umbraco.Core/Services/IContentServiceBase.cs b/src/Umbraco.Core/Services/IContentServiceBase.cs
index c40f49347f..ca87382494 100644
--- a/src/Umbraco.Core/Services/IContentServiceBase.cs
+++ b/src/Umbraco.Core/Services/IContentServiceBase.cs
@@ -1,7 +1,16 @@
-using Umbraco.Core.Models;
+using System;
+using System.Collections.Generic;
+using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
+ public interface IContentServiceBase : IContentServiceBase
+ where TItem: class, IContentBase
+ {
+ TItem GetById(Guid key);
+ Attempt Save(IEnumerable contents, int userId = Constants.Security.SuperUserId, bool raiseEvents = true);
+ }
+
///
/// Placeholder for sharing logic between the content, media (and member) services
/// TODO: Start sharing the logic!
diff --git a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs
index 4c818aa87c..3c91091f8c 100644
--- a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs
+++ b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs
@@ -58,7 +58,6 @@ namespace Umbraco.Core.Services
void Save(TItem item, int userId = Constants.Security.SuperUserId);
void Save(IEnumerable items, int userId = Constants.Security.SuperUserId);
-
void Delete(TItem item, int userId = Constants.Security.SuperUserId);
void Delete(IEnumerable item, int userId = Constants.Security.SuperUserId);
diff --git a/src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs b/src/Umbraco.Core/Services/IInstallationService.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs
rename to src/Umbraco.Core/Services/IInstallationService.cs
diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs
index c1537adbc8..aa6363cc36 100644
--- a/src/Umbraco.Core/Services/IMediaService.cs
+++ b/src/Umbraco.Core/Services/IMediaService.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Querying;
@@ -10,7 +9,7 @@ namespace Umbraco.Core.Services
///
/// Defines the Media Service, which is an easy access to operations involving
///
- public interface IMediaService : IContentServiceBase
+ public interface IMediaService : IContentServiceBase
{
int CountNotTrashed(string contentTypeAlias = null);
int Count(string mediaTypeAlias = null);
diff --git a/src/Umbraco.Core/Services/IRuntime.cs b/src/Umbraco.Core/Services/IRuntime.cs
index 8a1be721d0..d1254c219f 100644
--- a/src/Umbraco.Core/Services/IRuntime.cs
+++ b/src/Umbraco.Core/Services/IRuntime.cs
@@ -1,22 +1,15 @@
-using System;
+using Microsoft.Extensions.Hosting;
namespace Umbraco.Core
{
///
/// Defines the Umbraco runtime.
///
- public interface IRuntime
+ public interface IRuntime : IHostedService
{
///
/// Gets the runtime state.
///
IRuntimeState State { get; }
-
- void Start();
-
- ///
- /// Terminates the runtime.
- ///
- void Terminate();
}
}
diff --git a/src/Umbraco.Core/Services/IServerRegistrationService.cs b/src/Umbraco.Core/Services/IServerRegistrationService.cs
index 62bb68eb14..f0246dd287 100644
--- a/src/Umbraco.Core/Services/IServerRegistrationService.cs
+++ b/src/Umbraco.Core/Services/IServerRegistrationService.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Sync;
@@ -11,9 +11,8 @@ namespace Umbraco.Core.Services
/// Touches a server to mark it as active; deactivate stale servers.
///
/// The server URL.
- /// The server unique identity.
/// The time after which a server is considered stale.
- void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout);
+ void TouchServer(string serverAddress, TimeSpan staleTimeout);
///
/// Deactivates a server.
@@ -38,11 +37,6 @@ namespace Umbraco.Core.Services
/// from the database.
IEnumerable GetActiveServers(bool refresh = false);
- ///
- /// Gets the current server identity.
- ///
- string CurrentServerIdentity { get; }
-
///
/// Gets the role of the current server.
///
diff --git a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs b/src/Umbraco.Core/Services/InstallationService.cs
similarity index 87%
rename from src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs
rename to src/Umbraco.Core/Services/InstallationService.cs
index a1f74e0862..6e283a61d7 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs
+++ b/src/Umbraco.Core/Services/InstallationService.cs
@@ -1,8 +1,8 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
-namespace Umbraco.Core.Services.Implement
+namespace Umbraco.Core.Services
{
public class InstallationService : IInstallationService
{
diff --git a/src/Umbraco.Core/Services/UpgradeService.cs b/src/Umbraco.Core/Services/UpgradeService.cs
index ead5270b41..b36eac7789 100644
--- a/src/Umbraco.Core/Services/UpgradeService.cs
+++ b/src/Umbraco.Core/Services/UpgradeService.cs
@@ -1,10 +1,9 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Semver;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
-using Umbraco.Core.Services;
-namespace Umbraco.Core
+namespace Umbraco.Core.Services
{
public class UpgradeService : IUpgradeService
{
diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs b/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs
index 7438762295..f7dafac7a6 100644
--- a/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs
+++ b/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs
@@ -1,10 +1,10 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Umbraco.Core.Sync
{
///
- /// Holds a list of callbacks associated with implementations of .
+ /// Holds a list of callbacks associated with implementations of .
///
public class DatabaseServerMessengerCallbacks
{
diff --git a/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs b/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs
deleted file mode 100644
index f361eb7a67..0000000000
--- a/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Umbraco.Core.Services;
-
-namespace Umbraco.Core.Sync
-{
- ///
- /// A registrar that stores registered server nodes in the database.
- ///
- ///
- /// This is the default registrar which determines a server's role by using a master election process.
- /// The master election process doesn't occur until just after startup so this election process doesn't really affect the primary startup phase.
- ///
- public sealed class DatabaseServerRegistrar : IServerRegistrar
- {
- private readonly Lazy _registrationService;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The registration service.
- /// Some options.
- public DatabaseServerRegistrar(Lazy registrationService)
- {
- _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService));
- }
-
- ///
- /// Gets the registered servers.
- ///
- public IEnumerable Registrations => _registrationService.Value.GetActiveServers();
-
- ///
- /// Gets the role of the current server in the application environment.
- ///
- public ServerRole GetCurrentServerRole()
- {
- var service = _registrationService.Value;
- return service.GetCurrentServerRole();
- }
-
- }
-}
diff --git a/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs b/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs
new file mode 100644
index 0000000000..e4accd046b
--- /dev/null
+++ b/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs
@@ -0,0 +1,29 @@
+using System;
+using Umbraco.Core.Services;
+
+namespace Umbraco.Core.Sync
+{
+ ///
+ /// Gets the current server's based on active servers registered with
+ ///
+ ///
+ /// This is the default service which determines a server's role by using a master election process.
+ /// The master election process doesn't occur until just after startup so this election process doesn't really affect the primary startup phase.
+ ///
+ public sealed class ElectedServerRoleAccessor : IServerRoleAccessor
+ {
+ private readonly IServerRegistrationService _registrationService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The registration service.
+ /// Some options.
+ public ElectedServerRoleAccessor(IServerRegistrationService registrationService) => _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService));
+
+ ///
+ /// Gets the role of the current server in the application environment.
+ ///
+ public ServerRole CurrentServerRole => _registrationService.GetCurrentServerRole();
+ }
+}
diff --git a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs
deleted file mode 100644
index 560b7fb235..0000000000
--- a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Umbraco.Core.Sync
-{
- ///
- /// An implementation that works by storing messages in the database.
- ///
- public interface IBatchedDatabaseServerMessenger : IDatabaseServerMessenger
- {
- void FlushBatch();
- DatabaseServerMessengerCallbacks Callbacks { get; }
- void Startup();
- }
-}
diff --git a/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs
deleted file mode 100644
index a49cfdd023..0000000000
--- a/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Umbraco.Core.Sync
-{
- public interface IDatabaseServerMessenger: IServerMessenger
- {
- void Sync();
- }
-}
diff --git a/src/Umbraco.Core/Sync/IServerMessenger.cs b/src/Umbraco.Core/Sync/IServerMessenger.cs
index b8300b2d6d..df2d665057 100644
--- a/src/Umbraco.Core/Sync/IServerMessenger.cs
+++ b/src/Umbraco.Core/Sync/IServerMessenger.cs
@@ -1,21 +1,30 @@
-using System;
-using System.Collections.Generic;
+using System;
using Umbraco.Core.Cache;
namespace Umbraco.Core.Sync
{
///
- /// Broadcasts distributed cache notifications to all servers of a load balanced environment.
+ /// Transmits distributed cache notifications for all servers of a load balanced environment.
///
/// Also ensures that the notification is processed on the local environment.
public interface IServerMessenger
{
+ ///
+ /// Called to synchronize a server with queued notifications
+ ///
+ void Sync();
+
+ ///
+ /// Called to send/commit the queued messages created with the Perform methods
+ ///
+ void SendMessages();
+
///
/// Notifies the distributed cache, for a specified .
///
/// The ICacheRefresher.
/// The notification content.
- void PerformRefresh(ICacheRefresher refresher, TPayload[] payload);
+ void QueueRefresh(ICacheRefresher refresher, TPayload[] payload);
///
/// Notifies the distributed cache of specified item invalidation, for a specified .
@@ -24,7 +33,7 @@ namespace Umbraco.Core.Sync
/// The ICacheRefresher.
/// A function returning the unique identifier of items.
/// The invalidated items.
- void PerformRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances);
+ void QueueRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances);
///
/// Notifies the distributed cache of specified item invalidation, for a specified .
@@ -33,7 +42,7 @@ namespace Umbraco.Core.Sync
/// The ICacheRefresher.
/// A function returning the unique identifier of items.
/// The invalidated items.
- void PerformRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances);
+ void QueueRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances);
///
/// Notifies all servers of specified items removal, for a specified .
@@ -42,33 +51,33 @@ namespace Umbraco.Core.Sync
/// The ICacheRefresher.
/// A function returning the unique identifier of items.
/// The removed items.
- void PerformRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances);
+ void QueueRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances);
///
/// Notifies all servers of specified items removal, for a specified .
///
/// The ICacheRefresher.
/// The unique identifiers of the removed items.
- void PerformRemove(ICacheRefresher refresher, params int[] numericIds);
+ void QueueRemove(ICacheRefresher refresher, params int[] numericIds);
///
/// Notifies all servers of specified items invalidation, for a specified .
///
/// The ICacheRefresher.
/// The unique identifiers of the invalidated items.
- void PerformRefresh(ICacheRefresher refresher, params int[] numericIds);
+ void QueueRefresh(ICacheRefresher refresher, params int[] numericIds);
///
/// Notifies all servers of specified items invalidation, for a specified .
///
/// The ICacheRefresher.
/// The unique identifiers of the invalidated items.
- void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds);
+ void QueueRefresh(ICacheRefresher refresher, params Guid[] guidIds);
///
/// Notifies all servers of a global invalidation for a specified .
///
/// The ICacheRefresher.
- void PerformRefreshAll(ICacheRefresher refresher);
+ void QueueRefreshAll(ICacheRefresher refresher);
}
}
diff --git a/src/Umbraco.Core/Sync/IServerRegistrar.cs b/src/Umbraco.Core/Sync/IServerRegistrar.cs
deleted file mode 100644
index 780f865ad7..0000000000
--- a/src/Umbraco.Core/Sync/IServerRegistrar.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Collections.Generic;
-
-namespace Umbraco.Core.Sync
-{
- ///
- /// Provides server registrations to the distributed cache.
- ///
- public interface IServerRegistrar
- {
- ///
- /// Gets the server registrations.
- ///
- IEnumerable Registrations { get; }
-
- ///
- /// Gets the role of the current server in the application environment.
- ///
- ServerRole GetCurrentServerRole();
-
- }
-}
diff --git a/src/Umbraco.Core/Sync/IServerRoleAccessor.cs b/src/Umbraco.Core/Sync/IServerRoleAccessor.cs
new file mode 100644
index 0000000000..b23acbac7c
--- /dev/null
+++ b/src/Umbraco.Core/Sync/IServerRoleAccessor.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace Umbraco.Core.Sync
+{
+ ///
+ /// Gets the current server's
+ ///
+ public interface IServerRoleAccessor
+ {
+ ///
+ /// Gets the role of the current server in the application environment.
+ ///
+ ServerRole CurrentServerRole { get; }
+ }
+}
diff --git a/src/Umbraco.Core/Sync/SingleServerRegistrar.cs b/src/Umbraco.Core/Sync/SingleServerRegistrar.cs
deleted file mode 100644
index fe03e195b2..0000000000
--- a/src/Umbraco.Core/Sync/SingleServerRegistrar.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Umbraco.Web;
-
-namespace Umbraco.Core.Sync
-{
- ///
- /// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup performance
- ///
- ///
- /// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the
- /// which by default is done with master election by a database query. The master election process doesn't occur until just after startup
- /// so this micro optimization doesn't really affect the primary startup phase.
- ///
- public class SingleServerRegistrar : IServerRegistrar
- {
- private readonly IRequestAccessor _requestAccessor;
- private readonly Lazy _registrations;
-
- public IEnumerable Registrations => _registrations.Value;
-
- public SingleServerRegistrar(IRequestAccessor requestAccessor)
- {
- _requestAccessor = requestAccessor;
- _registrations = new Lazy(() => new IServerAddress[] { new ServerAddressImpl(_requestAccessor.GetApplicationUrl().ToString()) });
- }
-
- public ServerRole GetCurrentServerRole()
- {
- return ServerRole.Single;
- }
-
-
- private class ServerAddressImpl : IServerAddress
- {
- public ServerAddressImpl(string serverAddress)
- {
- ServerAddress = serverAddress;
- }
-
- public string ServerAddress { get; }
- }
- }
-}
diff --git a/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs
new file mode 100644
index 0000000000..65b9559522
--- /dev/null
+++ b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using Umbraco.Web;
+
+namespace Umbraco.Core.Sync
+{
+ ///
+ /// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup performance
+ ///
+ ///
+ /// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the
+ /// which by default is done with master election by a database query. The master election process doesn't occur until just after startup
+ /// so this micro optimization doesn't really affect the primary startup phase.
+ ///
+ public class SingleServerRoleAccessor : IServerRoleAccessor
+ {
+ public ServerRole CurrentServerRole => ServerRole.Single;
+ }
+}
diff --git a/src/Umbraco.Core/Trees/ISearchableTree.cs b/src/Umbraco.Core/Trees/ISearchableTree.cs
index 3d82d548c8..8f31c2c6ab 100644
--- a/src/Umbraco.Core/Trees/ISearchableTree.cs
+++ b/src/Umbraco.Core/Trees/ISearchableTree.cs
@@ -1,8 +1,8 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using Umbraco.Core.Composing;
using Umbraco.Web.Models.ContentEditing;
-namespace Umbraco.Web.Trees
+namespace Umbraco.Core.Trees
{
public interface ISearchableTree : IDiscoverable
{
diff --git a/src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs b/src/Umbraco.Core/Trees/SearchableApplicationTree.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs
rename to src/Umbraco.Core/Trees/SearchableApplicationTree.cs
index 346f106b84..ad6fb7f43f 100644
--- a/src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs
+++ b/src/Umbraco.Core/Trees/SearchableApplicationTree.cs
@@ -1,6 +1,4 @@
-using Umbraco.Web.Trees;
-
-namespace Umbraco.Web.Search
+namespace Umbraco.Core.Trees
{
public class SearchableApplicationTree
{
diff --git a/src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs b/src/Umbraco.Core/Trees/SearchableTreeCollection.cs
similarity index 97%
rename from src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs
rename to src/Umbraco.Core/Trees/SearchableTreeCollection.cs
index 5c251a857d..e562b763d4 100644
--- a/src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs
+++ b/src/Umbraco.Core/Trees/SearchableTreeCollection.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
@@ -6,7 +6,7 @@ using Umbraco.Core.Composing;
using Umbraco.Web.Services;
using Umbraco.Web.Trees;
-namespace Umbraco.Web.Search
+namespace Umbraco.Core.Trees
{
public class SearchableTreeCollection : BuilderCollectionBase
{
diff --git a/src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs
similarity index 81%
rename from src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs
rename to src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs
index a5e940b4a6..7922cf36ad 100644
--- a/src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs
+++ b/src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs
@@ -1,8 +1,7 @@
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.Composing;
-using Umbraco.Web.Trees;
-namespace Umbraco.Web.Search
+namespace Umbraco.Core.Trees
{
public class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase
{
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 28695d1673..febe8bd7ec 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -16,8 +16,10 @@
+
+
diff --git a/src/Umbraco.Core/UmbracoContextAccessorExtensions.cs b/src/Umbraco.Core/UmbracoContextAccessorExtensions.cs
index 74e2dd7380..a8521762c6 100644
--- a/src/Umbraco.Core/UmbracoContextAccessorExtensions.cs
+++ b/src/Umbraco.Core/UmbracoContextAccessorExtensions.cs
@@ -3,6 +3,7 @@ using Umbraco.Web;
namespace Umbraco.Core
{
+
public static class UmbracoContextAccessorExtensions
{
public static IUmbracoContext GetRequiredUmbracoContext(this IUmbracoContextAccessor umbracoContextAccessor)
diff --git a/src/Umbraco.Core/UmbracoContextExtensions.cs b/src/Umbraco.Core/UmbracoContextExtensions.cs
new file mode 100644
index 0000000000..06ae2aa497
--- /dev/null
+++ b/src/Umbraco.Core/UmbracoContextExtensions.cs
@@ -0,0 +1,12 @@
+using Umbraco.Web;
+
+namespace Umbraco.Core
+{
+ public static class UmbracoContextExtensions
+ {
+ ///
+ /// Boolean value indicating whether the current request is a front-end umbraco request
+ ///
+ public static bool IsFrontEndUmbracoRequest(this IUmbracoContext umbracoContext) => umbracoContext.PublishedRequest != null;
+ }
+}
diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs
index 0452373d55..ea846f7f7a 100644
--- a/src/Umbraco.Core/UriExtensions.cs
+++ b/src/Umbraco.Core/UriExtensions.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.IO;
using System.Linq;
using Microsoft.Extensions.Logging;
@@ -100,16 +100,13 @@ namespace Umbraco.Core
return false;
}
- //if its anything else we can assume it's back office
+ // if its anything else we can assume it's back office
return true;
}
///
/// Checks if the current uri is an install request
///
- ///
- ///
- ///
public static bool IsInstallerRequest(this Uri url, IHostingEnvironment hostingEnvironment)
{
var authority = url.GetLeftPart(UriPartial.Authority);
@@ -117,18 +114,14 @@ namespace Umbraco.Core
.TrimStart(authority)
.TrimStart("/");
- //check if this is in the umbraco back office
+ // check if this is in the umbraco back office
return afterAuthority.InvariantStartsWith(hostingEnvironment.ToAbsolute(Constants.SystemDirectories.Install).TrimStart("/"));
}
///
/// Checks if the uri is a request for the default back office page
///
- ///
- ///
- ///
- ///
- internal static bool IsDefaultBackOfficeRequest(this Uri url, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment)
+ public static bool IsDefaultBackOfficeRequest(this Uri url, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment)
{
var backOfficePath = globalSettings.GetBackOfficePath(hostingEnvironment);
if (url.AbsolutePath.InvariantEquals(backOfficePath.TrimEnd("/"))
@@ -138,6 +131,7 @@ namespace Umbraco.Core
{
return true;
}
+
return false;
}
diff --git a/src/Umbraco.Core/HybridUmbracoContextAccessor.cs b/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs
similarity index 100%
rename from src/Umbraco.Core/HybridUmbracoContextAccessor.cs
rename to src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs
diff --git a/src/Umbraco.Core/IUmbracoContext.cs b/src/Umbraco.Core/Web/IUmbracoContext.cs
similarity index 90%
rename from src/Umbraco.Core/IUmbracoContext.cs
rename to src/Umbraco.Core/Web/IUmbracoContext.cs
index 681dedbfd2..c034997d7e 100644
--- a/src/Umbraco.Core/IUmbracoContext.cs
+++ b/src/Umbraco.Core/Web/IUmbracoContext.cs
@@ -6,7 +6,7 @@ using Umbraco.Web.Routing;
namespace Umbraco.Web
{
- public interface IUmbracoContext
+ public interface IUmbracoContext : IDisposable
{
///
/// This is used internally for performance calculations, the ObjectCreated DateTime is set as soon as this
@@ -46,14 +46,10 @@ namespace Umbraco.Web
///
IDomainCache Domains { get; }
- ///
- /// Boolean value indicating whether the current request is a front-end umbraco request
- ///
- bool IsFrontEndUmbracoRequest { get; }
-
///
/// Gets/sets the PublishedRequest object
///
+ // TODO: Can we refactor this and not expose this mutable object here? Instead just expose IPublishedContent? A bunch of stuff would need to change but would be better
IPublishedRequest PublishedRequest { get; set; }
///
@@ -73,6 +69,5 @@ namespace Umbraco.Web
bool InPreviewMode { get; }
IDisposable ForcedPreview(bool preview);
- void Dispose();
}
}
diff --git a/src/Umbraco.Core/IUmbracoContextAccessor.cs b/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs
similarity index 100%
rename from src/Umbraco.Core/IUmbracoContextAccessor.cs
rename to src/Umbraco.Core/Web/IUmbracoContextAccessor.cs
diff --git a/src/Umbraco.Core/IUmbracoContextFactory.cs b/src/Umbraco.Core/Web/IUmbracoContextFactory.cs
similarity index 100%
rename from src/Umbraco.Core/IUmbracoContextFactory.cs
rename to src/Umbraco.Core/Web/IUmbracoContextFactory.cs
diff --git a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
index e2f2460d58..05315b05fe 100644
--- a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
+++ b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
-using Umbraco.Core;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
new file mode 100644
index 0000000000..5b4dd4f0ed
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
@@ -0,0 +1,96 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Umbraco.Core.Events;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.Sync;
+using Umbraco.Web;
+using Umbraco.Web.Cache;
+using Umbraco.Web.Routing;
+
+namespace Umbraco.Infrastructure.Cache
+{
+ ///
+ /// Ensures that distributed cache events are setup and the is initialized
+ ///
+ public sealed class DatabaseServerMessengerNotificationHandler : INotificationHandler
+ {
+ private readonly IServerMessenger _messenger;
+ private readonly IRequestAccessor _requestAccessor;
+ private readonly IUmbracoDatabaseFactory _databaseFactory;
+ private readonly IDistributedCacheBinder _distributedCacheBinder;
+ private readonly ILogger _logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DatabaseServerMessengerNotificationHandler(
+ IServerMessenger serverMessenger,
+ IRequestAccessor requestAccessor,
+ IUmbracoDatabaseFactory databaseFactory,
+ IDistributedCacheBinder distributedCacheBinder,
+ ILogger logger)
+ {
+ _requestAccessor = requestAccessor;
+ _databaseFactory = databaseFactory;
+ _distributedCacheBinder = distributedCacheBinder;
+ _logger = logger;
+ _messenger = serverMessenger;
+ }
+
+ ///
+ public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
+ {
+ // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services.
+ // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL
+ // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured).
+ // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available
+ // for the hosted services to use when the HTTP request is not available.
+ _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce;
+ _requestAccessor.EndRequest += EndRequest;
+
+ Startup();
+
+ return Task.CompletedTask;
+ }
+
+ private void Startup()
+ {
+ if (_databaseFactory.CanConnect == false)
+ {
+ _logger.LogWarning("Cannot connect to the database, distributed calls will not be enabled for this server.");
+ }
+ else
+ {
+ _distributedCacheBinder.BindEvents();
+
+ // Sync on startup, this will run through the messenger's initialization sequence
+ _messenger?.Sync();
+ }
+ }
+
+ // TODO: I don't really know or think that the Application Url plays a role anymore with the DB dist cache,
+ // this might be really old stuff. I 'think' all this is doing is ensuring that the IRequestAccessor.GetApplicationUrl
+ // is definitely called during the first request. If that is still required, that logic doesn't belong here. That logic
+ // should be part of it's own service/middleware. There's also TODO notes within IRequestAccessor.GetApplicationUrl directly
+ // mentioning that the property doesn't belong on that service either. This should be investigated and resolved in a separate task.
+ private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e)
+ {
+ if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
+ {
+ _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce;
+ EnsureApplicationUrl();
+ }
+ }
+
+ // By retrieving the application URL within the context of a request (as we are here in responding
+ // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for
+ // future requests that may not be within an HTTP request (e.g. from hosted services).
+ private void EnsureApplicationUrl() => _requestAccessor.GetApplicationUrl();
+
+ ///
+ /// Clear the batch on end request
+ ///
+ private void EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.SendMessages();
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs
deleted file mode 100644
index 7279eaf10c..0000000000
--- a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-
-namespace Umbraco.Web.Cache
-{
- ///
- /// Installs listeners on service events in order to refresh our caches.
- ///
- [ComposeBefore(typeof(ICoreComposer))] // runs before every other IUmbracoCoreComponent!
- public sealed class DistributedCacheBinderComposer : ComponentComposer, ICoreComposer
- {
- public override void Compose(IUmbracoBuilder builder)
- {
- base.Compose(builder);
-
- builder.Services.AddUnique();
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
deleted file mode 100644
index 8d2a2e19cc..0000000000
--- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Core.Services.Changes;
-using Umbraco.Core.Sync;
-using Umbraco.Web.Cache;
-using Umbraco.Web.PublishedCache;
-using Umbraco.Web.Routing;
-using Umbraco.Web.Search;
-
-namespace Umbraco.Web.Compose
-{
- ///
- /// Ensures that servers are automatically registered in the database, when using the database server registrar.
- ///
- ///
- /// At the moment servers are automatically registered upon first request and then on every
- /// request but not more than once per (configurable) period. This really is "for information & debug" purposes so
- /// we can look at the table and see what servers are registered - but the info is not used anywhere.
- /// Should we actually want to use this, we would need a better and more deterministic way of figuring
- /// out the "server address" ie the address to which server-to-server requests should be sent - because it
- /// probably is not the "current request address" - especially in multi-domains configurations.
- ///
- // during Initialize / Startup, we end up checking Examine, which needs to be initialized beforehand
- // TODO: should not be a strong dependency on "examine" but on an "indexing component"
- [ComposeAfter(typeof(ExamineComposer))]
-
- public sealed class DatabaseServerRegistrarAndMessengerComposer : ComponentComposer, ICoreComposer
- {
- public static DatabaseServerMessengerCallbacks GetCallbacks(IServiceProvider factory)
- {
- return new DatabaseServerMessengerCallbacks
- {
- //These callbacks will be executed if the server has not been synced
- // (i.e. it is a new server or the lastsynced.txt file has been removed)
- InitializingCallbacks = new Action[]
- {
- //rebuild the xml cache file if the server is not synced
- () =>
- {
- var publishedSnapshotService = factory.GetRequiredService();
-
- // rebuild the published snapshot caches entirely, if the server is not synced
- // this is equivalent to DistributedCache RefreshAll... but local only
- // (we really should have a way to reuse RefreshAll... locally)
- // note: refresh all content & media caches does refresh content types too
- publishedSnapshotService.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) });
- publishedSnapshotService.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _, out _);
- publishedSnapshotService.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _);
- },
-
- //rebuild indexes if the server is not synced
- // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
- // indexes then they can adjust this logic themselves.
- () =>
- {
- var indexRebuilder = factory.GetRequiredService();
- indexRebuilder.RebuildIndexes(false, 5000);
- }
- }
- };
- }
-
- public override void Compose(IUmbracoBuilder builder)
- {
- base.Compose(builder);
-
- builder.SetDatabaseServerMessengerCallbacks(GetCallbacks);
- builder.SetServerMessenger();
- }
- }
-
- public sealed class DatabaseServerRegistrarAndMessengerComponent : IComponent
- {
- private readonly IBatchedDatabaseServerMessenger _messenger;
- private readonly IRequestAccessor _requestAccessor;
-
- public DatabaseServerRegistrarAndMessengerComponent(
- IServerMessenger serverMessenger,
- IRequestAccessor requestAccessor)
- {
- _requestAccessor = requestAccessor;
- _messenger = serverMessenger as IBatchedDatabaseServerMessenger;
- }
-
- public void Initialize()
- {
- // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services.
- // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL
- // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured).
- // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available
- // for the hosted services to use when the HTTP request is not available.
- _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce;
-
- // Must come last, as it references some _variables
- _messenger?.Startup();
- }
-
- public void Terminate()
- { }
-
- private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e)
- {
- if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
- {
- _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce;
- EnsureApplicationUrl();
- }
- }
-
- private void EnsureApplicationUrl()
- {
- // By retrieving the application URL within the context of a request (as we are here in responding
- // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for
- // future requests that may not be within an HTTP request (e.g. from hosted services).
- _requestAccessor.GetApplicationUrl();
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
deleted file mode 100644
index dd3a800821..0000000000
--- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.IO;
-using Microsoft.Extensions.Logging;
-using Umbraco.Core.Composing;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.Manifest;
-using Umbraco.Net;
-
-namespace Umbraco.Core.Compose
-{
- public sealed class ManifestWatcherComponent : IComponent
- {
- private readonly IHostingEnvironment _hosting;
- private readonly ILoggerFactory _loggerFactory;
- private readonly IHostingEnvironment _hostingEnvironment;
- private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
-
- // if configured and in debug mode, a ManifestWatcher watches App_Plugins folders for
- // package.manifest chances and restarts the application on any change
- private ManifestWatcher _mw;
-
- public ManifestWatcherComponent(IHostingEnvironment hosting, ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment, IUmbracoApplicationLifetime umbracoApplicationLifetime)
- {
- _hosting = hosting;
- _loggerFactory = loggerFactory;
- _hostingEnvironment = hostingEnvironment;
- _umbracoApplicationLifetime = umbracoApplicationLifetime;
- }
-
- public void Initialize()
- {
- if (_hosting.IsDebugMode == false) return;
-
- //if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false)
- // return;
-
- var appPlugins = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins);
- if (Directory.Exists(appPlugins) == false) return;
-
- _mw = new ManifestWatcher(_loggerFactory.CreateLogger(), _umbracoApplicationLifetime);
- _mw.Start(Directory.GetDirectories(appPlugins));
- }
-
- public void Terminate()
- {
- if (_mw == null) return;
-
- _mw.Dispose();
- _mw = null;
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComposer.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComposer.cs
deleted file mode 100644
index 786a3ed0ce..0000000000
--- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComposer.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using Umbraco.Core.Composing;
-
-namespace Umbraco.Core.Compose
-{
- public class ManifestWatcherComposer : ComponentComposer, ICoreComposer
- { }
-}
diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
index 0fee815560..79066dedd7 100644
--- a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
+++ b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
@@ -1,5 +1,4 @@
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
namespace Umbraco.Web.Compose
diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs
deleted file mode 100644
index 31b3133e4d..0000000000
--- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Web.Install;
-using Umbraco.Web.Install.InstallSteps;
-using Umbraco.Web.Install.Models;
-
-namespace Umbraco.Web.Composing.CompositionExtensions
-{
- public static class Installer
- {
- public static IUmbracoBuilder ComposeInstaller(this IUmbracoBuilder builder)
- {
- // register the installer steps
-
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
-
- // TODO: Add these back once we have a compatible Starter kit
- // composition.Services.AddScoped();
- // composition.Services.AddScoped();
- // composition.Services.AddScoped();
-
- builder.Services.AddScoped();
-
- builder.Services.AddTransient();
- builder.Services.AddUnique();
-
- return builder;
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
deleted file mode 100644
index 7c17a8a338..0000000000
--- a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Microsoft.Extensions.Hosting;
-
-namespace Umbraco.Core.Composing
-{
- ///
- /// Extends the to enable Umbraco to be used as the service container.
- ///
- public static class HostBuilderExtensions
- {
- ///
- /// Assigns a custom service provider factory to use Umbraco's container
- ///
- ///
- ///
- public static IHostBuilder UseUmbraco(this IHostBuilder builder)
- {
- return builder;
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/CompositionExtensions.cs b/src/Umbraco.Infrastructure/CompositionExtensions.cs
deleted file mode 100644
index 703c35e06b..0000000000
--- a/src/Umbraco.Infrastructure/CompositionExtensions.cs
+++ /dev/null
@@ -1,335 +0,0 @@
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Composing;
-using Umbraco.Core.Dictionary;
-using Umbraco.Core.IO;
-using Umbraco.Core.Logging.Viewer;
-using Umbraco.Core.Manifest;
-using Umbraco.Core.Models.PublishedContent;
-using Umbraco.Core.PackageActions;
-using Umbraco.Core.Persistence.Mappers;
-using Umbraco.Core.PropertyEditors;
-using Umbraco.Core.Strings;
-using Umbraco.Core.Sync;
-using Umbraco.Web.Media.EmbedProviders;
-using Umbraco.Web.Search;
-
-namespace Umbraco.Core
-{
- ///
- /// Provides extension methods to the class.
- ///
- public static partial class CompositionExtensions
- {
- #region Collection Builders
-
- ///
- /// Gets the cache refreshers collection builder.
- ///
- /// The builder.
- public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the mappers collection builder.
- ///
- /// The builder.
- public static MapperCollectionBuilder Mappers(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the package actions collection builder.
- ///
- /// The builder.
- internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the data editor collection builder.
- ///
- /// The builder.
- public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the data value reference factory collection builder.
- ///
- /// The builder.
- public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the property value converters collection builder.
- ///
- /// The builder.
- public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the url segment providers collection builder.
- ///
- /// The builder.
- public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the validators collection builder.
- ///
- /// The builder.
- internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the manifest filter collection builder.
- ///
- /// The builder.
- public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the backoffice OEmbed Providers collection builder.
- ///
- /// The builder.
- public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the back office searchable tree collection builder
- ///
- ///
- ///
- public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- #endregion
-
- #region Uniques
-
- ///
- /// Sets the culture dictionary factory.
- ///
- /// The type of the factory.
- /// The builder.
- public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder)
- where T : class, ICultureDictionaryFactory
- {
- builder.Services.AddUnique();
- }
-
- ///
- /// Sets the culture dictionary factory.
- ///
- /// The builder.
- /// A function creating a culture dictionary factory.
- public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the culture dictionary factory.
- ///
- /// The builder.
- /// A factory.
- public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, ICultureDictionaryFactory factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the published content model factory.
- ///
- /// The type of the factory.
- /// The builder.
- public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder)
- where T : class, IPublishedModelFactory
- {
- builder.Services.AddUnique();
- }
-
- ///
- /// Sets the published content model factory.
- ///
- /// The builder.
- /// A function creating a published content model factory.
- public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the published content model factory.
- ///
- /// The builder.
- /// A published content model factory.
- public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, IPublishedModelFactory factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the server registrar.
- ///
- /// The type of the server registrar.
- /// The builder.
- public static void SetServerRegistrar(this IUmbracoBuilder builder)
- where T : class, IServerRegistrar
- {
- builder.Services.AddUnique();
- }
-
- ///
- /// Sets the server registrar.
- ///
- /// The builder.
- /// A function creating a server registrar.
- public static void SetServerRegistrar(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the server registrar.
- ///
- /// The builder.
- /// A server registrar.
- public static void SetServerRegistrar(this IUmbracoBuilder builder, IServerRegistrar registrar)
- {
- builder.Services.AddUnique(registrar);
- }
-
- ///
- /// Sets the server messenger.
- ///
- /// The type of the server registrar.
- /// The builder.
- public static void SetServerMessenger(this IUmbracoBuilder builder)
- where T : class, IServerMessenger
- {
- builder.Services.AddUnique();
- }
-
- ///
- /// Sets the server messenger.
- ///
- /// The builder.
- /// A function creating a server messenger.
- public static void SetServerMessenger(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the server messenger.
- ///
- /// The builder.
- /// A server messenger.
- public static void SetServerMessenger(this IUmbracoBuilder builder, IServerMessenger registrar)
- {
- builder.Services.AddUnique(registrar);
- }
-
- ///
- /// Sets the database server messenger options.
- ///
- /// The builder.
- /// A function creating the options.
- /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default.
- public static void SetDatabaseServerMessengerCallbacks(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the database server messenger options.
- ///
- /// The builder.
- /// Options.
- /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default.
- public static void SetDatabaseServerMessengerOptions(this IUmbracoBuilder builder, DatabaseServerMessengerCallbacks options)
- {
- builder.Services.AddUnique(options);
- }
-
- ///
- /// Sets the short string helper.
- ///
- /// The type of the short string helper.
- /// The builder.
- public static void SetShortStringHelper(this IUmbracoBuilder builder)
- where T : class, IShortStringHelper
- {
- builder.Services.AddUnique();
- }
-
- ///
- /// Sets the short string helper.
- ///
- /// The builder.
- /// A function creating a short string helper.
- public static void SetShortStringHelper(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the short string helper.
- ///
- /// A builder.
- /// A short string helper.
- public static void SetShortStringHelper(this IUmbracoBuilder builder, IShortStringHelper helper)
- {
- builder.Services.AddUnique(helper);
- }
-
- ///
- /// Sets the underlying media filesystem.
- ///
- /// A builder.
- /// A filesystem factory.
- ///
- /// Using this helper will ensure that your IFileSystem implementation is wrapped by the ShadowWrapper
- ///
- public static void SetMediaFileSystem(this IUmbracoBuilder builder, Func filesystemFactory)
- => builder.Services.AddUnique(factory =>
- {
- var fileSystems = factory.GetRequiredService();
- return fileSystems.GetFileSystem(filesystemFactory(factory));
- });
-
- ///
- /// Sets the log viewer.
- ///
- /// The type of the log viewer.
- /// The builder.
- public static void SetLogViewer(this IUmbracoBuilder builder)
- where T : class, ILogViewer
- {
- builder.Services.AddUnique();
- }
-
- ///
- /// Sets the log viewer.
- ///
- /// The builder.
- /// A function creating a log viewer.
- public static void SetLogViewer(this IUmbracoBuilder builder, Func factory)
- {
- builder.Services.AddUnique(factory);
- }
-
- ///
- /// Sets the log viewer.
- ///
- /// A builder.
- /// A log viewer.
- public static void SetLogViewer(this IUmbracoBuilder builder, ILogViewer viewer)
- {
- builder.Services.AddUnique(viewer);
- }
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Infrastructure/Configuration/NCronTabParser.cs b/src/Umbraco.Infrastructure/Configuration/NCronTabParser.cs
index 5642c882e6..ca25563730 100644
--- a/src/Umbraco.Infrastructure/Configuration/NCronTabParser.cs
+++ b/src/Umbraco.Infrastructure/Configuration/NCronTabParser.cs
@@ -1,9 +1,8 @@
-using System;
+using System;
using NCrontab;
namespace Umbraco.Core.Configuration
{
-
public class NCronTabParser : ICronTabParser
{
public bool IsValidCronTab(string cronTab)
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs
new file mode 100644
index 0000000000..4da9c93fb3
--- /dev/null
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs
@@ -0,0 +1,25 @@
+using Umbraco.Core.Cache;
+using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.Manifest;
+using Umbraco.Core.PackageActions;
+using Umbraco.Core.Persistence.Mappers;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Strings;
+using Umbraco.Core.Trees;
+using Umbraco.Web.Media.EmbedProviders;
+
+namespace Umbraco.Infrastructure.DependencyInjection
+{
+ ///
+ /// Provides extension methods to the class.
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Gets the mappers collection builder.
+ ///
+ /// The builder.
+ public static MapperCollectionBuilder Mappers(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+ }
+}
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs
new file mode 100644
index 0000000000..94c1e3dcfa
--- /dev/null
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs
@@ -0,0 +1,208 @@
+using System.Runtime.InteropServices;
+using Examine;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.Models;
+using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.Install;
+using Umbraco.Core.Logging.Serilog.Enrichers;
+using Umbraco.Core.Mail;
+using Umbraco.Core.Manifest;
+using Umbraco.Core.Media;
+using Umbraco.Core.Migrations;
+using Umbraco.Core.Migrations.Install;
+using Umbraco.Core.Migrations.PostMigrations;
+using Umbraco.Core.Models.PublishedContent;
+using Umbraco.Core.Packaging;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.PropertyEditors.ValueConverters;
+using Umbraco.Core.Runtime;
+using Umbraco.Core.Scoping;
+using Umbraco.Core.Serialization;
+using Umbraco.Core.Strings;
+using Umbraco.Core.Templates;
+using Umbraco.Examine;
+using Umbraco.Infrastructure.Examine;
+using Umbraco.Infrastructure.Logging.Serilog.Enrichers;
+using Umbraco.Infrastructure.Media;
+using Umbraco.Infrastructure.Runtime;
+using Umbraco.Web;
+using Umbraco.Web.HealthCheck;
+using Umbraco.Web.HealthCheck.NotificationMethods;
+using Umbraco.Web.Install;
+using Umbraco.Web.Media;
+using Umbraco.Web.Migrations.PostMigrations;
+using Umbraco.Web.Models.PublishedContent;
+using Umbraco.Web.PropertyEditors;
+using Umbraco.Web.PropertyEditors.ValueConverters;
+using Umbraco.Web.PublishedCache;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Search;
+using Umbraco.Web.Trees;
+
+namespace Umbraco.Infrastructure.DependencyInjection
+{
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Adds all core Umbraco services required to run which may be replaced later in the pipeline
+ ///
+ public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder)
+ {
+ builder
+ .AddMainDom()
+ .AddLogging();
+
+ builder.Services.AddUnique();
+ builder.Services.AddUnique(factory => factory.GetRequiredService().CreateDatabase());
+ builder.Services.AddUnique(factory => factory.GetRequiredService().SqlContext);
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+
+ // composers
+ builder
+ .AddRepositories()
+ .AddServices()
+ .AddCoreMappingProfiles()
+ .AddFileSystems();
+
+ // 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
+ builder.Mappers().AddCoreMappers();
+
+ // register the scope provider
+ builder.Services.AddUnique(); // implements both IScopeProvider and IScopeAccessor
+ builder.Services.AddUnique(f => f.GetRequiredService());
+ builder.Services.AddUnique(f => f.GetRequiredService());
+
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+
+ // register database builder
+ // *not* a singleton, don't want to keep it around
+ builder.Services.AddTransient();
+
+ // register manifest parser, will be injected in collection builders where needed
+ builder.Services.AddUnique();
+
+ // register the manifest filter collection builder (collection is empty by default)
+ builder.ManifestFilters();
+
+ builder.MediaUrlGenerators()
+ .Add()
+ .Add();
+
+ builder.Services.AddUnique();
+
+ builder.Services.AddUnique(factory
+ => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService>().Value)));
+
+ builder.Services.AddUnique(factory => new MigrationBuilder(factory));
+
+ builder.Services.AddUnique();
+
+ // register the published snapshot accessor - the "current" published snapshot is in the umbraco context
+ builder.Services.AddUnique();
+
+ builder.Services.AddUnique();
+
+ // Config manipulator
+ builder.Services.AddUnique();
+
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+
+ // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be
+ // discovered when CoreBootManager configures the converters. We will remove the basic one defined
+ // in core so that the more enhanced version is active.
+ builder.PropertyValueConverters()
+ .Remove();
+
+ builder.Services.AddUnique();
+
+ builder.Services.AddUnique();
+
+ // register *all* checks, except those marked [HideFromTypeFinder] of course
+ builder.Services.AddUnique();
+
+ builder.Services.AddUnique();
+
+ builder.Services.AddScoped();
+
+ // replace
+ builder.Services.AddUnique();
+
+ builder.Services.AddUnique();
+
+ builder.Services.AddScoped();
+
+ builder.Services.AddUnique();
+ builder.Services.AddScoped(factory =>
+ {
+ var umbCtx = factory.GetRequiredService();
+ return new PublishedContentQuery(umbCtx.UmbracoContext.PublishedSnapshot, factory.GetRequiredService(), factory.GetRequiredService());
+ });
+
+ // register accessors for cultures
+ builder.Services.AddUnique();
+
+ builder.Services.AddSingleton();
+
+ builder.Services.AddUnique();
+
+ // Register noop versions for examine to be overridden by examine
+ builder.Services.AddUnique