diff --git a/build/NuSpecs/tools/Web.config.install.xdt b/build/NuSpecs/tools/Web.config.install.xdt index 2b79f95c70..f118fa8c3a 100644 --- a/build/NuSpecs/tools/Web.config.install.xdt +++ b/build/NuSpecs/tools/Web.config.install.xdt @@ -5,9 +5,9 @@ -
+
-
+
diff --git a/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs b/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs index cc57b96f1b..b682e20358 100644 --- a/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs +++ b/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; @@ -80,6 +81,7 @@ namespace Umbraco.Core.Collections } } + #region IRememberBeingDirty public bool IsDirty() { return this.OfType().Any(x => x.IsDirty()); @@ -150,5 +152,8 @@ namespace Umbraco.Core.Collections { return Enumerable.Empty(); } + + public event PropertyChangedEventHandler PropertyChanged; // noop + #endregion } } diff --git a/src/Umbraco.Core/Composing/ComponentCollection.cs b/src/Umbraco.Abstractions/Composing/ComponentCollection.cs similarity index 100% rename from src/Umbraco.Core/Composing/ComponentCollection.cs rename to src/Umbraco.Abstractions/Composing/ComponentCollection.cs diff --git a/src/Umbraco.Core/Composing/ComponentCollectionBuilder.cs b/src/Umbraco.Abstractions/Composing/ComponentCollectionBuilder.cs similarity index 100% rename from src/Umbraco.Core/Composing/ComponentCollectionBuilder.cs rename to src/Umbraco.Abstractions/Composing/ComponentCollectionBuilder.cs diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Abstractions/Composing/Composition.cs similarity index 96% rename from src/Umbraco.Core/Composing/Composition.cs rename to src/Umbraco.Abstractions/Composing/Composition.cs index 34c5296dce..8cf02151e8 100644 --- a/src/Umbraco.Core/Composing/Composition.cs +++ b/src/Umbraco.Abstractions/Composing/Composition.cs @@ -27,19 +27,12 @@ namespace Umbraco.Core.Composing /// A logger. /// The runtime state. /// Optional configs. - public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs = null) + public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs) { _register = register; TypeLoader = typeLoader; Logger = logger; RuntimeState = runtimeState; - - if (configs == null) - { - configs = new Configs(); - configs.AddCoreConfigs(); - } - Configs = configs; } @@ -131,12 +124,14 @@ namespace Umbraco.Core.Composing builder.RegisterWith(_register); _builders.Clear(); // no point keep them around - Configs.RegisterWith(_register); - IFactory factory = null; + + Configs.RegisterWith(_register, () => factory); + // ReSharper disable once AccessToModifiedClosure -- on purpose _register.Register(_ => factory, Lifetime.Singleton); factory = _register.CreateFactory(); + return factory; } diff --git a/src/Umbraco.Core/Composing/IComposer.cs b/src/Umbraco.Abstractions/Composing/IComposer.cs similarity index 100% rename from src/Umbraco.Core/Composing/IComposer.cs rename to src/Umbraco.Abstractions/Composing/IComposer.cs diff --git a/src/Umbraco.Core/Composing/ICoreComposer.cs b/src/Umbraco.Abstractions/Composing/ICoreComposer.cs similarity index 100% rename from src/Umbraco.Core/Composing/ICoreComposer.cs rename to src/Umbraco.Abstractions/Composing/ICoreComposer.cs diff --git a/src/Umbraco.Core/CompositionExtensions_Uniques.cs b/src/Umbraco.Abstractions/CompositionExtensions_Uniques.cs similarity index 100% rename from src/Umbraco.Core/CompositionExtensions_Uniques.cs rename to src/Umbraco.Abstractions/CompositionExtensions_Uniques.cs diff --git a/src/Umbraco.Abstractions/ConfigConnectionStringExtensions.cs b/src/Umbraco.Abstractions/ConfigConnectionStringExtensions.cs new file mode 100644 index 0000000000..693b8a433e --- /dev/null +++ b/src/Umbraco.Abstractions/ConfigConnectionStringExtensions.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; +using System.Linq; +using Umbraco.Core.Configuration; + +namespace Umbraco.Core +{ + + public static class ConfigConnectionStringExtensions + { + public static bool IsConnectionStringConfigured(this ConfigConnectionString databaseSettings) + { + var dbIsSqlCe = false; + if (databaseSettings?.ProviderName != null) + dbIsSqlCe = databaseSettings.ProviderName == Constants.DbProviderNames.SqlCe; + var sqlCeDatabaseExists = false; + if (dbIsSqlCe) + { + var parts = databaseSettings.ConnectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + var dataSourcePart = parts.FirstOrDefault(x => x.InvariantStartsWith("Data Source=")); + if (dataSourcePart != null) + { + var datasource = dataSourcePart.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()); + var filePath = datasource.Replace("Data Source=", string.Empty); + sqlCeDatabaseExists = File.Exists(filePath); + } + } + + // Either the connection details are not fully specified or it's a SQL CE database that doesn't exist yet + if (databaseSettings == null + || string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) || string.IsNullOrWhiteSpace(databaseSettings.ProviderName) + || (dbIsSqlCe && sqlCeDatabaseExists == false)) + { + return false; + } + + return true; + } + } +} diff --git a/src/Umbraco.Abstractions/Configuration/ConfigConnectionString.cs b/src/Umbraco.Abstractions/Configuration/ConfigConnectionString.cs new file mode 100644 index 0000000000..e9ac944b85 --- /dev/null +++ b/src/Umbraco.Abstractions/Configuration/ConfigConnectionString.cs @@ -0,0 +1,16 @@ +namespace Umbraco.Core.Configuration +{ + public class ConfigConnectionString + { + public ConfigConnectionString(string connectionString, string providerName, string name) + { + ConnectionString = connectionString; + ProviderName = providerName; + Name = name; + } + + public string ConnectionString { get; } + public string ProviderName { get; } + public string Name { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/Configs.cs b/src/Umbraco.Abstractions/Configuration/Configs.cs similarity index 82% rename from src/Umbraco.Core/Configuration/Configs.cs rename to src/Umbraco.Abstractions/Configuration/Configs.cs index 51e1a327a0..abb06d525f 100644 --- a/src/Umbraco.Core/Configuration/Configs.cs +++ b/src/Umbraco.Abstractions/Configuration/Configs.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Configuration; using Umbraco.Core.Composing; -using Umbraco.Core.Logging; namespace Umbraco.Core.Configuration { @@ -15,8 +13,16 @@ namespace Umbraco.Core.Configuration /// public class Configs { + private readonly Func _configSectionResolver; + + public Configs(Func configSectionResolver) + { + _configSectionResolver = configSectionResolver ?? throw new ArgumentNullException(nameof(configSectionResolver)); + } + private readonly Dictionary> _configs = new Dictionary>(); private Dictionary> _registerings = new Dictionary>(); + private Lazy _factory; /// /// Gets a configuration. @@ -60,7 +66,7 @@ namespace Umbraco.Core.Configuration _configs[typeOfConfig] = new Lazy(() => { - if (Current.HasFactory) return Current.Factory.GetInstance(); + if (!(_factory is null)) return _factory.Value.GetInstance(); throw new InvalidOperationException($"Cannot get configuration of type {typeOfConfig} during composition."); }); _registerings[typeOfConfig] = register => register.Register(configFactory, Lifetime.Singleton); @@ -75,7 +81,7 @@ namespace Umbraco.Core.Configuration Add(() => GetConfig(sectionName)); } - private static TConfig GetConfig(string sectionName) + private TConfig GetConfig(string sectionName) where TConfig : class { // note: need to use SafeCallContext here because ConfigurationManager.GetSection ends up getting AppDomain.Evidence @@ -83,10 +89,9 @@ namespace Umbraco.Core.Configuration using (new SafeCallContext()) { - if ((ConfigurationManager.GetSection(sectionName) is TConfig config)) + if ((_configSectionResolver(sectionName) is TConfig config)) return config; - var ex = new ConfigurationErrorsException($"Could not get configuration section \"{sectionName}\" from config files."); - Current.Logger.Error(ex, "Config error"); + var ex = new InvalidOperationException($"Could not get configuration section \"{sectionName}\" from config files."); throw ex; } } @@ -94,12 +99,14 @@ namespace Umbraco.Core.Configuration /// /// Registers configurations in a register. /// - public void RegisterWith(IRegister register) + public void RegisterWith(IRegister register, Func factory) { // do it only once if (_registerings == null) throw new InvalidOperationException("Configurations have already been registered."); + _factory = new Lazy(factory); + register.Register(this); foreach (var registering in _registerings.Values) diff --git a/src/Umbraco.Core/ConfigsExtensions.cs b/src/Umbraco.Abstractions/Configuration/ConfigsExtensions.cs similarity index 68% rename from src/Umbraco.Core/ConfigsExtensions.cs rename to src/Umbraco.Abstractions/Configuration/ConfigsExtensions.cs index 70af1d3cdb..3beb7ee3cd 100644 --- a/src/Umbraco.Core/ConfigsExtensions.cs +++ b/src/Umbraco.Abstractions/Configuration/ConfigsExtensions.cs @@ -19,6 +19,9 @@ namespace Umbraco.Core public static IGlobalSettings Global(this Configs configs) => configs.GetConfig(); + public static IConnectionStrings ConnectionStrings(this Configs configs) + => configs.GetConfig(); + public static IUmbracoSettingsSection Settings(this Configs configs) => configs.GetConfig(); @@ -28,25 +31,20 @@ namespace Umbraco.Core public static IGridConfig Grids(this Configs configs) => configs.GetConfig(); - internal static CoreDebug CoreDebug(this Configs configs) - => configs.GetConfig(); + public static ICoreDebug CoreDebug(this Configs configs) + => configs.GetConfig(); - public static void AddCoreConfigs(this Configs configs) + public static void AddCoreConfigs(this Configs configs, IIOHelper ioHelper) { - var configDir = new DirectoryInfo(Current.IOHelper.MapPath(Constants.SystemDirectories.Config)); + var configDir = new DirectoryInfo(ioHelper.MapPath(Constants.SystemDirectories.Config)); - configs.Add(() => new GlobalSettings(Current.IOHelper)); - configs.Add("umbracoConfiguration/settings"); - configs.Add("umbracoConfiguration/HealthChecks"); - - configs.Add(() => new CoreDebug()); // GridConfig depends on runtime caches, manifest parsers... and cannot be available during composition configs.Add(factory => new GridConfig( factory.GetInstance(), factory.GetInstance(), configDir, - factory.GetInstance(), + factory.GetInstance(), factory.GetInstance().Debug)); } } diff --git a/src/Umbraco.Abstractions/Configuration/GlobalSettingsExtensions.cs b/src/Umbraco.Abstractions/Configuration/GlobalSettingsExtensions.cs new file mode 100644 index 0000000000..4d8039dfbb --- /dev/null +++ b/src/Umbraco.Abstractions/Configuration/GlobalSettingsExtensions.cs @@ -0,0 +1,45 @@ +using System; +using Umbraco.Core.IO; + +namespace Umbraco.Core.Configuration +{ + public static class GlobalSettingsExtensions + { + private static string _mvcArea; + + + /// + /// This returns the string of the MVC Area route. + /// + /// + /// This will return the MVC area that we will route all custom routes through like surface controllers, etc... + /// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin + /// we will convert the '/' to '-' and use that as the path. its a bit lame but will work. + /// + /// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something + /// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco". + /// + public static string GetUmbracoMvcArea(this IGlobalSettings globalSettings, IIOHelper ioHelper) + { + if (_mvcArea != null) return _mvcArea; + + _mvcArea = GetUmbracoMvcAreaNoCache(globalSettings, ioHelper); + + return _mvcArea; + } + + internal static string GetUmbracoMvcAreaNoCache(this IGlobalSettings globalSettings, IIOHelper ioHelper) + { + if (globalSettings.Path.IsNullOrWhiteSpace()) + { + throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified"); + } + + var path = globalSettings.Path; + if (path.StartsWith(ioHelper.Root)) // beware of TrimStart, see U4-2518 + path = path.Substring(ioHelper.Root.Length); + return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower(); + } + + } +} diff --git a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs b/src/Umbraco.Abstractions/Configuration/Grid/GridConfig.cs similarity index 78% rename from src/Umbraco.Core/Configuration/Grid/GridConfig.cs rename to src/Umbraco.Abstractions/Configuration/Grid/GridConfig.cs index 9aead74886..de4f7ccd5a 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs +++ b/src/Umbraco.Abstractions/Configuration/Grid/GridConfig.cs @@ -5,9 +5,9 @@ using Umbraco.Core.Manifest; namespace Umbraco.Core.Configuration.Grid { - class GridConfig : IGridConfig + public class GridConfig : IGridConfig { - public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, ManifestParser manifestParser, bool isDebug) + public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, IManifestParser manifestParser, bool isDebug) { EditorsConfig = new GridEditorsConfig(logger, appCaches, configFolder, manifestParser, isDebug); } diff --git a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs b/src/Umbraco.Abstractions/Configuration/Grid/GridEditorsConfig.cs similarity index 86% rename from src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs rename to src/Umbraco.Abstractions/Configuration/Grid/GridEditorsConfig.cs index d434da8c70..a1ebf008fc 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs +++ b/src/Umbraco.Abstractions/Configuration/Grid/GridEditorsConfig.cs @@ -13,10 +13,10 @@ namespace Umbraco.Core.Configuration.Grid private readonly ILogger _logger; private readonly AppCaches _appCaches; private readonly DirectoryInfo _configFolder; - private readonly ManifestParser _manifestParser; + private readonly IManifestParser _manifestParser; private readonly bool _isDebug; - public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, ManifestParser manifestParser, bool isDebug) + public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, IManifestParser manifestParser, bool isDebug) { _logger = logger; _appCaches = appCaches; @@ -29,9 +29,9 @@ namespace Umbraco.Core.Configuration.Grid { get { - List GetResult() + List GetResult() { - var editors = new List(); + var editors = new List(); var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js"); if (File.Exists(gridConfig)) { @@ -59,7 +59,7 @@ namespace Umbraco.Core.Configuration.Grid //cache the result if debugging is disabled var result = _isDebug ? GetResult() - : _appCaches.RuntimeCache.GetCacheItem>(typeof(GridEditorsConfig) + ".Editors",GetResult, TimeSpan.FromMinutes(10)); + : _appCaches.RuntimeCache.GetCacheItem>(typeof(GridEditorsConfig) + ".Editors",GetResult, TimeSpan.FromMinutes(10)); return result; } diff --git a/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs b/src/Umbraco.Abstractions/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs similarity index 52% rename from src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs rename to src/Umbraco.Abstractions/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs index 6556c19c32..95e5ca8e03 100644 --- a/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs +++ b/src/Umbraco.Abstractions/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs @@ -1,7 +1,10 @@ -namespace Umbraco.Core.Configuration.HealthChecks +using System.Runtime.Serialization; + +namespace Umbraco.Core.Configuration.HealthChecks { public enum HealthCheckNotificationVerbosity { + Summary, Detailed } diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IDisabledHealthCheck.cs b/src/Umbraco.Abstractions/Configuration/HealthChecks/IDisabledHealthCheck.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/IDisabledHealthCheck.cs rename to src/Umbraco.Abstractions/Configuration/HealthChecks/IDisabledHealthCheck.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs b/src/Umbraco.Abstractions/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs rename to src/Umbraco.Abstractions/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs b/src/Umbraco.Abstractions/Configuration/HealthChecks/IHealthChecks.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs rename to src/Umbraco.Abstractions/Configuration/HealthChecks/IHealthChecks.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethod.cs b/src/Umbraco.Abstractions/Configuration/HealthChecks/INotificationMethod.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/INotificationMethod.cs rename to src/Umbraco.Abstractions/Configuration/HealthChecks/INotificationMethod.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethodSettings.cs b/src/Umbraco.Abstractions/Configuration/HealthChecks/INotificationMethodSettings.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/INotificationMethodSettings.cs rename to src/Umbraco.Abstractions/Configuration/HealthChecks/INotificationMethodSettings.cs diff --git a/src/Umbraco.Abstractions/Configuration/IConfigsFactory.cs b/src/Umbraco.Abstractions/Configuration/IConfigsFactory.cs new file mode 100644 index 0000000000..3e36f3fb55 --- /dev/null +++ b/src/Umbraco.Abstractions/Configuration/IConfigsFactory.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Core.Configuration +{ + public interface IConfigsFactory + { + Configs Create(); + } +} diff --git a/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs b/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs new file mode 100644 index 0000000000..0d33378669 --- /dev/null +++ b/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Core.Configuration +{ + public interface IConnectionStrings + { + ConfigConnectionString this[string key] + { + get; + } + } +} diff --git a/src/Umbraco.Abstractions/Configuration/ICoreDebug.cs b/src/Umbraco.Abstractions/Configuration/ICoreDebug.cs new file mode 100644 index 0000000000..4ff2a1a300 --- /dev/null +++ b/src/Umbraco.Abstractions/Configuration/ICoreDebug.cs @@ -0,0 +1,17 @@ +namespace Umbraco.Core.Configuration +{ + public interface ICoreDebug + { + /// + /// When set to true, Scope logs the stack trace for any scope that gets disposed without being completed. + /// this helps troubleshooting rogue scopes that we forget to complete + /// + bool LogUncompletedScopes { get; } + + /// + /// When set to true, the Logger creates a mini dump of w3wp in ~/App_Data/MiniDump whenever it logs + /// an error due to a ThreadAbortException that is due to a timeout. + /// + bool DumpOnTimeoutThreadAbort { get; } + } +} diff --git a/src/Umbraco.Abstractions/Configuration/IGlobalSettings.cs b/src/Umbraco.Abstractions/Configuration/IGlobalSettings.cs index 48371bd11b..da8b8cd373 100644 --- a/src/Umbraco.Abstractions/Configuration/IGlobalSettings.cs +++ b/src/Umbraco.Abstractions/Configuration/IGlobalSettings.cs @@ -5,6 +5,9 @@ /// public interface IGlobalSettings { + // fixme: Review this class, it is now just a dumping ground for config options (based basically on whatever might be in appSettings), + // our config classes should be named according to what they are configuring. + /// /// Gets the reserved urls from web.config. /// @@ -63,14 +66,39 @@ /// LocalTempStorage LocalTempStorageLocation { get; } - /// - /// Gets the location of temporary files. - /// - string LocalTempPath { get; } - string UmbracoPath { get; } string UmbracoCssPath { get; } string UmbracoScriptsPath { get; } string UmbracoMediaPath { get; } + bool DebugMode { get; } + + bool IsSmtpServerConfigured { get; } + + /// + /// Gets a value indicating whether the runtime should enter Install level when the database is missing. + /// + /// + /// By default, when a database connection string is configured but it is not possible to + /// connect to the database, the runtime enters the BootFailed level. If this options is set to true, + /// it enters the Install level instead. + /// It is then up to the implementor, that is setting this value, to take over the installation + /// sequence. + /// + bool InstallMissingDatabase { get; } + + /// + /// Gets a value indicating whether the runtime should enter Install level when the database is empty. + /// + /// + /// By default, when a database connection string is configured and it is possible to connect to + /// the database, but the database is empty, the runtime enters the BootFailed level. If this options + /// is set to true, it enters the Install level instead. + /// It is then up to the implementor, that is setting this value, to take over the installation + /// sequence. + /// + bool InstallEmptyDatabase { get; } + bool DisableElectionForSingleServer { get; } + string RegisterType { get; } + string DatabaseFactoryServerVersion { get; } } } diff --git a/src/Umbraco.Abstractions/Configuration/IUmbracoVersion.cs b/src/Umbraco.Abstractions/Configuration/IUmbracoVersion.cs new file mode 100644 index 0000000000..1bdce0ec7c --- /dev/null +++ b/src/Umbraco.Abstractions/Configuration/IUmbracoVersion.cs @@ -0,0 +1,56 @@ +using System; +using Semver; + +namespace Umbraco.Core.Configuration +{ + public interface IUmbracoVersion + { + /// + /// Gets the non-semantic version of the Umbraco code. + /// + Version Current { get; } + + /// + /// Gets the semantic version comments of the Umbraco code. + /// + string Comment { get; } + + /// + /// Gets the assembly version of the Umbraco code. + /// + /// + /// The assembly version is the value of the . + /// Is the one that the CLR checks for compatibility. Therefore, it changes only on + /// hard-breaking changes (for instance, on new major versions). + /// + Version AssemblyVersion { get; } + + /// + /// Gets the assembly file version of the Umbraco code. + /// + /// + /// The assembly version is the value of the . + /// + Version AssemblyFileVersion { get; } + + /// + /// Gets the semantic version of the Umbraco code. + /// + /// + /// The semantic version is the value of the . + /// It is the full version of Umbraco, including comments. + /// + SemVersion SemanticVersion { get; } + + /// + /// Gets the "local" version of the site. + /// + /// + /// Three things have a version, really: the executing code, the database model, + /// and the site/files. The database model version is entirely managed via migrations, + /// and changes during an upgrade. The executing code version changes when new code is + /// deployed. The site/files version changes during an upgrade. + /// + SemVersion LocalVersion { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Abstractions/Configuration/UmbracoVersion.cs similarity index 74% rename from src/Umbraco.Core/Configuration/UmbracoVersion.cs rename to src/Umbraco.Abstractions/Configuration/UmbracoVersion.cs index 2f615d26b3..dd96e6edd7 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Abstractions/Configuration/UmbracoVersion.cs @@ -8,11 +8,19 @@ namespace Umbraco.Core.Configuration /// /// Represents the version of the executing code. /// - public static class UmbracoVersion + public class UmbracoVersion : IUmbracoVersion { - static UmbracoVersion() + private readonly IGlobalSettings _globalSettings; + + public UmbracoVersion(IGlobalSettings globalSettings) + :this() { - var umbracoCoreAssembly = typeof(UmbracoVersion).Assembly; + _globalSettings = globalSettings; + } + + public UmbracoVersion() + { + var umbracoCoreAssembly = typeof(SemVersion).Assembly; // gets the value indicated by the AssemblyVersion attribute AssemblyVersion = umbracoCoreAssembly.GetName().Version; @@ -32,12 +40,12 @@ namespace Umbraco.Core.Configuration /// Gets the non-semantic version of the Umbraco code. /// // TODO: rename to Version - public static Version Current { get; } + public Version Current { get; } /// /// Gets the semantic version comments of the Umbraco code. /// - public static string Comment => SemanticVersion.Prerelease; + public string Comment => SemanticVersion.Prerelease; /// /// Gets the assembly version of the Umbraco code. @@ -47,7 +55,7 @@ namespace Umbraco.Core.Configuration /// Is the one that the CLR checks for compatibility. Therefore, it changes only on /// hard-breaking changes (for instance, on new major versions). /// - public static Version AssemblyVersion {get; } + public Version AssemblyVersion {get; } /// /// Gets the assembly file version of the Umbraco code. @@ -55,7 +63,7 @@ namespace Umbraco.Core.Configuration /// /// The assembly version is the value of the . /// - public static Version AssemblyFileVersion { get; } + public Version AssemblyFileVersion { get; } /// /// Gets the semantic version of the Umbraco code. @@ -64,7 +72,7 @@ namespace Umbraco.Core.Configuration /// The semantic version is the value of the . /// It is the full version of Umbraco, including comments. /// - public static SemVersion SemanticVersion { get; } + public SemVersion SemanticVersion { get; } /// /// Gets the "local" version of the site. @@ -75,21 +83,11 @@ namespace Umbraco.Core.Configuration /// and changes during an upgrade. The executing code version changes when new code is /// deployed. The site/files version changes during an upgrade. /// - public static SemVersion LocalVersion - { + public SemVersion LocalVersion { get { - try - { - // TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings - var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus]; - return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null; - } - catch - { - return null; - } - } - } + var value = _globalSettings.ConfigurationStatus; + return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null; + } } } } diff --git a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs b/src/Umbraco.Abstractions/Events/CancellableEnumerableObjectEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs rename to src/Umbraco.Abstractions/Events/CancellableEnumerableObjectEventArgs.cs diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs b/src/Umbraco.Abstractions/Events/CancellableObjectEventArgsOfTEventObject.cs similarity index 100% rename from src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs rename to src/Umbraco.Abstractions/Events/CancellableObjectEventArgsOfTEventObject.cs diff --git a/src/Umbraco.Core/Events/CopyEventArgs.cs b/src/Umbraco.Abstractions/Events/CopyEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/CopyEventArgs.cs rename to src/Umbraco.Abstractions/Events/CopyEventArgs.cs diff --git a/src/Umbraco.Core/Events/DeleteEventArgs.cs b/src/Umbraco.Abstractions/Events/DeleteEventArgs.cs similarity index 99% rename from src/Umbraco.Core/Events/DeleteEventArgs.cs rename to src/Umbraco.Abstractions/Events/DeleteEventArgs.cs index 07bbe562db..5be669886e 100644 --- a/src/Umbraco.Core/Events/DeleteEventArgs.cs +++ b/src/Umbraco.Abstractions/Events/DeleteEventArgs.cs @@ -100,7 +100,7 @@ namespace Umbraco.Core.Events public IEnumerable DeletedEntities { get => EventObject; - internal set => EventObject = value; + set => EventObject = value; } /// diff --git a/src/Umbraco.Core/Events/DeleteRevisionsEventArgs.cs b/src/Umbraco.Abstractions/Events/DeleteRevisionsEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/DeleteRevisionsEventArgs.cs rename to src/Umbraco.Abstractions/Events/DeleteRevisionsEventArgs.cs diff --git a/src/Umbraco.Core/Events/EventExtensions.cs b/src/Umbraco.Abstractions/Events/EventExtensions.cs similarity index 100% rename from src/Umbraco.Core/Events/EventExtensions.cs rename to src/Umbraco.Abstractions/Events/EventExtensions.cs diff --git a/src/Umbraco.Core/Events/MoveEventArgs.cs b/src/Umbraco.Abstractions/Events/MoveEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/MoveEventArgs.cs rename to src/Umbraco.Abstractions/Events/MoveEventArgs.cs diff --git a/src/Umbraco.Core/Events/NewEventArgs.cs b/src/Umbraco.Abstractions/Events/NewEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/NewEventArgs.cs rename to src/Umbraco.Abstractions/Events/NewEventArgs.cs diff --git a/src/Umbraco.Core/Events/PublishEventArgs.cs b/src/Umbraco.Abstractions/Events/PublishEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/PublishEventArgs.cs rename to src/Umbraco.Abstractions/Events/PublishEventArgs.cs diff --git a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs b/src/Umbraco.Abstractions/Events/RecycleBinEventArgs.cs similarity index 95% rename from src/Umbraco.Core/Events/RecycleBinEventArgs.cs rename to src/Umbraco.Abstractions/Events/RecycleBinEventArgs.cs index 796952de98..3f0f3784a2 100644 --- a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs +++ b/src/Umbraco.Abstractions/Events/RecycleBinEventArgs.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Umbraco.Core.Models; namespace Umbraco.Core.Events { diff --git a/src/Umbraco.Core/Events/RolesEventArgs.cs b/src/Umbraco.Abstractions/Events/RolesEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/RolesEventArgs.cs rename to src/Umbraco.Abstractions/Events/RolesEventArgs.cs diff --git a/src/Umbraco.Core/Events/RollbackEventArgs.cs b/src/Umbraco.Abstractions/Events/RollbackEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/RollbackEventArgs.cs rename to src/Umbraco.Abstractions/Events/RollbackEventArgs.cs diff --git a/src/Umbraco.Core/Events/SaveEventArgs.cs b/src/Umbraco.Abstractions/Events/SaveEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/SaveEventArgs.cs rename to src/Umbraco.Abstractions/Events/SaveEventArgs.cs diff --git a/src/Umbraco.Core/Events/SendToPublishEventArgs.cs b/src/Umbraco.Abstractions/Events/SendToPublishEventArgs.cs similarity index 100% rename from src/Umbraco.Core/Events/SendToPublishEventArgs.cs rename to src/Umbraco.Abstractions/Events/SendToPublishEventArgs.cs diff --git a/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs b/src/Umbraco.Abstractions/Events/TransientEventMessagesFactory.cs similarity index 81% rename from src/Umbraco.Core/Events/TransientEventMessagesFactory.cs rename to src/Umbraco.Abstractions/Events/TransientEventMessagesFactory.cs index bd2e12dc17..7a0947c990 100644 --- a/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs +++ b/src/Umbraco.Abstractions/Events/TransientEventMessagesFactory.cs @@ -3,7 +3,7 @@ /// /// A simple/default transient messages factory /// - internal class TransientEventMessagesFactory : IEventMessagesFactory + public class TransientEventMessagesFactory : IEventMessagesFactory { public EventMessages Get() { diff --git a/src/Umbraco.Abstractions/IO/IIOHelper.cs b/src/Umbraco.Abstractions/IO/IIOHelper.cs index 735aed4813..b4a1007c2d 100644 --- a/src/Umbraco.Abstractions/IO/IIOHelper.cs +++ b/src/Umbraco.Abstractions/IO/IIOHelper.cs @@ -19,6 +19,7 @@ namespace Umbraco.Core.IO string MapPath(string path, bool useHttpContext); string MapPath(string path); + /// /// Verifies that the current filepath matches a directory where the user is allowed to edit a file. /// diff --git a/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs b/src/Umbraco.Abstractions/Logging/DebugDiagnosticsLogger.cs similarity index 77% rename from src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs rename to src/Umbraco.Abstractions/Logging/DebugDiagnosticsLogger.cs index d1bde55306..552daba713 100644 --- a/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs +++ b/src/Umbraco.Abstractions/Logging/DebugDiagnosticsLogger.cs @@ -7,6 +7,13 @@ namespace Umbraco.Core.Logging /// public class DebugDiagnosticsLogger : ILogger { + private readonly IMessageTemplates _messageTemplates; + + public DebugDiagnosticsLogger(IMessageTemplates messageTemplates) + { + _messageTemplates = messageTemplates; + } + public bool IsEnabled(Type reporting, LogLevel level) => true; @@ -31,7 +38,7 @@ namespace Umbraco.Core.Logging /// public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName); } /// @@ -61,7 +68,7 @@ namespace Umbraco.Core.Logging /// public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName); } /// @@ -79,7 +86,7 @@ namespace Umbraco.Core.Logging /// public void Warn(Type reporting, string message, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message, propertyValues), reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(message, propertyValues), reporting.FullName); } /// @@ -91,7 +98,7 @@ namespace Umbraco.Core.Logging /// public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName); } /// @@ -103,7 +110,7 @@ namespace Umbraco.Core.Logging /// public void Info(Type reporting, string messageTemplate, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues), reporting.FullName); } /// @@ -115,7 +122,7 @@ namespace Umbraco.Core.Logging /// public void Debug(Type reporting, string messageTemplate, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues), reporting.FullName); } /// @@ -127,7 +134,7 @@ namespace Umbraco.Core.Logging /// public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues) { - System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName); + System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues), reporting.FullName); } } } diff --git a/src/Umbraco.Abstractions/Logging/IMessageTemplates.cs b/src/Umbraco.Abstractions/Logging/IMessageTemplates.cs new file mode 100644 index 0000000000..b455e4af21 --- /dev/null +++ b/src/Umbraco.Abstractions/Logging/IMessageTemplates.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Core.Logging +{ + /// + /// Provides tools to support message templates. + /// + public interface IMessageTemplates + { + string Render(string messageTemplate, params object[] args); + } +} diff --git a/src/Umbraco.Core/Logging/LogProfiler.cs b/src/Umbraco.Abstractions/Logging/LogProfiler.cs similarity index 97% rename from src/Umbraco.Core/Logging/LogProfiler.cs rename to src/Umbraco.Abstractions/Logging/LogProfiler.cs index 74dae545b4..294f92dad3 100644 --- a/src/Umbraco.Core/Logging/LogProfiler.cs +++ b/src/Umbraco.Abstractions/Logging/LogProfiler.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Logging /// /// Implements by writing profiling results to an . /// - internal class LogProfiler : IProfiler + public class LogProfiler : IProfiler { private readonly ILogger _logger; diff --git a/src/Umbraco.Core/Logging/LoggingTaskExtension.cs b/src/Umbraco.Abstractions/Logging/LoggingTaskExtension.cs similarity index 100% rename from src/Umbraco.Core/Logging/LoggingTaskExtension.cs rename to src/Umbraco.Abstractions/Logging/LoggingTaskExtension.cs diff --git a/src/Umbraco.Core/Logging/VoidProfiler.cs b/src/Umbraco.Abstractions/Logging/VoidProfiler.cs similarity index 92% rename from src/Umbraco.Core/Logging/VoidProfiler.cs rename to src/Umbraco.Abstractions/Logging/VoidProfiler.cs index 24eb8e81c3..51bec521a3 100644 --- a/src/Umbraco.Core/Logging/VoidProfiler.cs +++ b/src/Umbraco.Abstractions/Logging/VoidProfiler.cs @@ -2,7 +2,7 @@ namespace Umbraco.Core.Logging { - internal class VoidProfiler : IProfiler + public class VoidProfiler : IProfiler { private readonly VoidDisposable _disposable = new VoidDisposable(); diff --git a/src/Umbraco.Abstractions/Models/Entities/EntityExtensions.cs b/src/Umbraco.Abstractions/Models/Entities/EntityExtensions.cs index 1e51f81d88..2df08f207d 100644 --- a/src/Umbraco.Abstractions/Models/Entities/EntityExtensions.cs +++ b/src/Umbraco.Abstractions/Models/Entities/EntityExtensions.cs @@ -11,7 +11,6 @@ namespace Umbraco.Core.Models.Entities { var now = DateTime.Now; - // just in case if (entity.CreateDate == default) { entity.CreateDate = now; diff --git a/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs b/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs index 77611ebc3d..b6983773b1 100644 --- a/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs +++ b/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Runtime.Serialization; using Umbraco.Core.Exceptions; @@ -23,7 +24,7 @@ namespace Umbraco.Core.Models.Entities /// Gets an entity representing "root". /// public static readonly IEntitySlim Root = new EntitySlim { Path = "-1", Name = "root", HasChildren = true }; - + // implement IEntity /// @@ -121,66 +122,10 @@ namespace Umbraco.Core.Models.Entities #endregion - #region IRememberBeingDirty - - // IEntitySlim does *not* track changes, but since it indirectly implements IUmbracoEntity, - // and therefore IRememberBeingDirty, we have to have those methods - which all throw. - - public bool IsDirty() + public void ResetIdentity() { - throw new WontImplementException(); + Id = default; + Key = Guid.Empty; } - - public bool IsPropertyDirty(string propName) - { - throw new WontImplementException(); - } - - public IEnumerable GetDirtyProperties() - { - throw new WontImplementException(); - } - - public void ResetDirtyProperties() - { - throw new WontImplementException(); - } - - public void DisableChangeTracking() - { - // noop - } - - public void EnableChangeTracking() - { - // noop - } - - public bool WasDirty() - { - throw new WontImplementException(); - } - - public bool WasPropertyDirty(string propertyName) - { - throw new WontImplementException(); - } - - public void ResetWereDirtyProperties() - { - throw new WontImplementException(); - } - - public void ResetDirtyProperties(bool rememberDirty) - { - throw new WontImplementException(); - } - - public IEnumerable GetWereDirtyProperties() - { - throw new WontImplementException(); - } - - #endregion } } diff --git a/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs b/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs index 57a8a581f0..03e2f19c70 100644 --- a/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs +++ b/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel; namespace Umbraco.Core.Models.Entities { @@ -36,5 +37,7 @@ namespace Umbraco.Core.Models.Entities /// Enables change tracking. /// void EnableChangeTracking(); + + event PropertyChangedEventHandler PropertyChanged; } } diff --git a/src/Umbraco.Abstractions/Models/Entities/IEntity.cs b/src/Umbraco.Abstractions/Models/Entities/IEntity.cs index 0b060e4dbd..7aafcbeccb 100644 --- a/src/Umbraco.Abstractions/Models/Entities/IEntity.cs +++ b/src/Umbraco.Abstractions/Models/Entities/IEntity.cs @@ -41,5 +41,7 @@ namespace Umbraco.Core.Models.Entities /// Gets a value indicating whether the entity has an identity. /// bool HasIdentity { get; } + + void ResetIdentity(); } } diff --git a/src/Umbraco.Abstractions/Models/Entities/IUmbracoEntity.cs b/src/Umbraco.Abstractions/Models/Entities/IUmbracoEntity.cs index e5f628b098..f76ec2438a 100644 --- a/src/Umbraco.Abstractions/Models/Entities/IUmbracoEntity.cs +++ b/src/Umbraco.Abstractions/Models/Entities/IUmbracoEntity.cs @@ -2,6 +2,7 @@ namespace Umbraco.Core.Models.Entities { + /// /// Represents an entity that can be managed by the entity service. /// @@ -10,6 +11,6 @@ namespace Umbraco.Core.Models.Entities /// IUmbracoEntities can be retrieved with the IEntityService. /// An IUmbracoEntity can participate in notifications. /// - public interface IUmbracoEntity : ITreeEntity, IRememberBeingDirty + public interface IUmbracoEntity : ITreeEntity { } } diff --git a/src/Umbraco.Abstractions/Models/IContentBase.cs b/src/Umbraco.Abstractions/Models/IContentBase.cs index 1864996379..1aade803b8 100644 --- a/src/Umbraco.Abstractions/Models/IContentBase.cs +++ b/src/Umbraco.Abstractions/Models/IContentBase.cs @@ -11,7 +11,7 @@ namespace Umbraco.Core.Models /// Content items are documents, medias and members. /// Content items have a content type, and properties. /// - public interface IContentBase : IUmbracoEntity + public interface IContentBase : IUmbracoEntity, IRememberBeingDirty { /// /// Integer Id of the default ContentType diff --git a/src/Umbraco.Core/Models/IContentType.cs b/src/Umbraco.Abstractions/Models/IContentType.cs similarity index 100% rename from src/Umbraco.Core/Models/IContentType.cs rename to src/Umbraco.Abstractions/Models/IContentType.cs diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Abstractions/Models/IContentTypeBase.cs similarity index 92% rename from src/Umbraco.Core/Models/IContentTypeBase.cs rename to src/Umbraco.Abstractions/Models/IContentTypeBase.cs index ed87c5f320..d65e2dcdfb 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Abstractions/Models/IContentTypeBase.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Models /// Defines the base for a ContentType with properties that /// are shared between ContentTypes and MediaTypes. /// - public interface IContentTypeBase : IUmbracoEntity + public interface IContentTypeBase : IUmbracoEntity, IRememberBeingDirty { /// /// Gets or Sets the Alias of the ContentType @@ -103,17 +103,17 @@ namespace Umbraco.Core.Models /// /// Gets all local property types all local property groups or ungrouped. /// - IEnumerable PropertyTypes { get; } + IEnumerable PropertyTypes { get; } /// /// Gets or sets the local property types that do not belong to a group. /// - IEnumerable NoGroupPropertyTypes { get; set; } + IEnumerable NoGroupPropertyTypes { get; set; } /// /// Removes a PropertyType from the current ContentType /// - /// Alias of the to remove + /// Alias of the to remove void RemovePropertyType(string propertyTypeAlias); /// @@ -132,17 +132,17 @@ namespace Umbraco.Core.Models /// /// Adds a PropertyType to a specific PropertyGroup /// - /// to add + /// to add /// Name of the PropertyGroup to add the PropertyType to /// Returns True if PropertyType was added, otherwise False - bool AddPropertyType(PropertyType propertyType, string propertyGroupName); + bool AddPropertyType(IPropertyType propertyType, string propertyGroupName); /// /// Adds a PropertyType, which does not belong to a PropertyGroup. /// - /// to add + /// to add /// Returns True if PropertyType was added, otherwise False - bool AddPropertyType(PropertyType propertyType); + bool AddPropertyType(IPropertyType propertyType); /// /// Adds a PropertyGroup. diff --git a/src/Umbraco.Core/Models/IContentTypeComposition.cs b/src/Umbraco.Abstractions/Models/IContentTypeComposition.cs similarity index 97% rename from src/Umbraco.Core/Models/IContentTypeComposition.cs rename to src/Umbraco.Abstractions/Models/IContentTypeComposition.cs index 675d3cd268..17b6881487 100644 --- a/src/Umbraco.Core/Models/IContentTypeComposition.cs +++ b/src/Umbraco.Abstractions/Models/IContentTypeComposition.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Models /// /// Gets the property types for the entire composition. /// - IEnumerable CompositionPropertyTypes { get; } + IEnumerable CompositionPropertyTypes { get; } /// /// Adds a new ContentType to the list of composite ContentTypes diff --git a/src/Umbraco.Core/Models/IDataType.cs b/src/Umbraco.Abstractions/Models/IDataType.cs similarity index 94% rename from src/Umbraco.Core/Models/IDataType.cs rename to src/Umbraco.Abstractions/Models/IDataType.cs index c7e682e4a2..39278abdc1 100644 --- a/src/Umbraco.Core/Models/IDataType.cs +++ b/src/Umbraco.Abstractions/Models/IDataType.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Models /// /// Represents a data type. /// - public interface IDataType : IUmbracoEntity + public interface IDataType : IUmbracoEntity, IRememberBeingDirty { /// /// Gets or sets the property editor. diff --git a/src/Umbraco.Abstractions/Models/IDictionaryTranslation.cs b/src/Umbraco.Abstractions/Models/IDictionaryTranslation.cs index 5cbec40b81..8510e5c520 100644 --- a/src/Umbraco.Abstractions/Models/IDictionaryTranslation.cs +++ b/src/Umbraco.Abstractions/Models/IDictionaryTranslation.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models { - public interface IDictionaryTranslation : IEntity + public interface IDictionaryTranslation : IEntity, IRememberBeingDirty { /// /// Gets or sets the for the translation diff --git a/src/Umbraco.Abstractions/Models/IFile.cs b/src/Umbraco.Abstractions/Models/IFile.cs index 0d98c90ffb..835c9bf434 100644 --- a/src/Umbraco.Abstractions/Models/IFile.cs +++ b/src/Umbraco.Abstractions/Models/IFile.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.Models /// Defines a File /// /// Used for Scripts, Stylesheets and Templates - public interface IFile : IEntity + public interface IFile : IEntity, IRememberBeingDirty { /// /// Gets the Name of the File including extension diff --git a/src/Umbraco.Core/Models/IMediaType.cs b/src/Umbraco.Abstractions/Models/IMediaType.cs similarity index 86% rename from src/Umbraco.Core/Models/IMediaType.cs rename to src/Umbraco.Abstractions/Models/IMediaType.cs index 25a5d0fa35..90fdc97ad7 100644 --- a/src/Umbraco.Core/Models/IMediaType.cs +++ b/src/Umbraco.Abstractions/Models/IMediaType.cs @@ -1,6 +1,4 @@ -using Umbraco.Core.Persistence.Mappers; - -namespace Umbraco.Core.Models +namespace Umbraco.Core.Models { /// /// Defines a ContentType, which Media is based on diff --git a/src/Umbraco.Core/Models/IMember.cs b/src/Umbraco.Abstractions/Models/IMember.cs similarity index 100% rename from src/Umbraco.Core/Models/IMember.cs rename to src/Umbraco.Abstractions/Models/IMember.cs diff --git a/src/Umbraco.Core/Models/IMemberType.cs b/src/Umbraco.Abstractions/Models/IMemberType.cs similarity index 100% rename from src/Umbraco.Core/Models/IMemberType.cs rename to src/Umbraco.Abstractions/Models/IMemberType.cs diff --git a/src/Umbraco.Abstractions/Models/IProperty.cs b/src/Umbraco.Abstractions/Models/IProperty.cs index 35a151af10..44e84d9b68 100644 --- a/src/Umbraco.Abstractions/Models/IProperty.cs +++ b/src/Umbraco.Abstractions/Models/IProperty.cs @@ -33,13 +33,9 @@ namespace Umbraco.Core.Models /// void SetValue(object value, string culture = null, string segment = null); - /// - /// Resets the entity identity. - /// - void ResetIdentity(); - int PropertyTypeId { get; } void PublishValues(string culture = "*", string segment = "*"); void UnpublishValues(string culture = "*", string segment = "*"); + } } diff --git a/src/Umbraco.Abstractions/Models/IPropertyType.cs b/src/Umbraco.Abstractions/Models/IPropertyType.cs index e70ee39933..6ed5dbd1cb 100644 --- a/src/Umbraco.Abstractions/Models/IPropertyType.cs +++ b/src/Umbraco.Abstractions/Models/IPropertyType.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Runtime.Serialization; using Umbraco.Core.Models.Entities; @@ -9,62 +10,62 @@ namespace Umbraco.Core.Models /// /// Gets of sets the name of the property type. /// - string Name { get; } + string Name { get; set; } /// /// Gets of sets the alias of the property type. /// - string Alias { get; } + string Alias { get; set; } /// /// Gets of sets the description of the property type. /// - string Description { get; } + string Description { get; set; } /// /// Gets or sets the identifier of the datatype for this property type. /// - int DataTypeId { get; } + int DataTypeId { get; set; } - Guid DataTypeKey { get; } + Guid DataTypeKey { get; set; } /// /// Gets or sets the alias of the property editor for this property type. /// - string PropertyEditorAlias { get; } + string PropertyEditorAlias { get; set; } /// /// Gets or sets the database type for storing value for this property type. /// - ValueStorageType ValueStorageType { get; } + ValueStorageType ValueStorageType { get; set; } /// /// Gets or sets the identifier of the property group this property type belongs to. /// /// For generic properties, the value is null. - Lazy PropertyGroupId { get; } + Lazy PropertyGroupId { get; set; } /// /// Gets of sets a value indicating whether a value for this property type is required. /// - bool Mandatory { get; } + bool Mandatory { get; set; } /// /// Gets of sets the sort order of the property type. /// - int SortOrder { get; } + int SortOrder { get; set; } /// /// Gets or sets the regular expression validating the property values. /// - string ValidationRegExp { get; } + string ValidationRegExp { get; set; } - bool SupportsPublishing { get; } + bool SupportsPublishing { get; set; } /// /// Gets or sets the content variation of the property type. /// - ContentVariation Variations { get; } + ContentVariation Variations { get; set; } /// /// Determines whether the property type supports a combination of culture and segment. @@ -74,14 +75,5 @@ namespace Umbraco.Core.Models /// A value indicating whether wildcards are valid. bool SupportsVariation(string culture, string segment, bool wildcards = false); - /// - /// Converts a value assigned to a property. - /// - /// - /// The input value can be pretty much anything, and is converted to the actual CLR type - /// expected by the property (eg an integer if the property values are integers). - /// Throws if the value cannot be converted. - /// - object ConvertAssignedValue(object value); } } diff --git a/src/Umbraco.Abstractions/Models/ISimpleContentType.cs b/src/Umbraco.Abstractions/Models/ISimpleContentType.cs index 740db8e73f..52364cfa1e 100644 --- a/src/Umbraco.Abstractions/Models/ISimpleContentType.cs +++ b/src/Umbraco.Abstractions/Models/ISimpleContentType.cs @@ -1,14 +1,15 @@ -using Umbraco.Core.Models.Entities; +using System; namespace Umbraco.Core.Models { /// /// Represents a simplified view of a content type. /// - public interface ISimpleContentType : IUmbracoEntity + public interface ISimpleContentType { - new int Id { get; } - new string Name { get; } + int Id { get; } + Guid Key { get; } + string Name { get; } /// /// Gets the alias of the content type. diff --git a/src/Umbraco.Abstractions/Models/IStylesheet.cs b/src/Umbraco.Abstractions/Models/IStylesheet.cs index 737118d646..bc2d870ea4 100644 --- a/src/Umbraco.Abstractions/Models/IStylesheet.cs +++ b/src/Umbraco.Abstractions/Models/IStylesheet.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models { - public interface IStylesheet : IFile, IRememberBeingDirty + public interface IStylesheet : IFile { /// /// Returns a list of umbraco back office enabled stylesheet properties diff --git a/src/Umbraco.Abstractions/Models/MacroProperty.cs b/src/Umbraco.Abstractions/Models/MacroProperty.cs index 9dfb81cf71..6714baf17b 100644 --- a/src/Umbraco.Abstractions/Models/MacroProperty.cs +++ b/src/Umbraco.Abstractions/Models/MacroProperty.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class MacroProperty : BeingDirtyBase, IMacroProperty, IRememberBeingDirty, IDeepCloneable + public class MacroProperty : BeingDirtyBase, IMacroProperty { public MacroProperty() { diff --git a/src/Umbraco.Abstractions/Models/Membership/ContentPermissionSet.cs b/src/Umbraco.Abstractions/Models/Membership/ContentPermissionSet.cs index f683db2830..fcf1228e69 100644 --- a/src/Umbraco.Abstractions/Models/Membership/ContentPermissionSet.cs +++ b/src/Umbraco.Abstractions/Models/Membership/ContentPermissionSet.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Models.Membership /// Represents an -> user group & permission key value pair collection /// /// - /// This implements purely so it can be used with the repository layer which is why it's explicitly implemented. + /// This implements purely so it can be used with the repository layer which is why it's explicitly implemented. /// public class ContentPermissionSet : EntityPermissionSet, IEntity { @@ -37,6 +37,8 @@ namespace Umbraco.Core.Models.Membership get { return EntityId > 0; } } + void IEntity.ResetIdentity() => throw new InvalidOperationException($"Resetting identity on {nameof(ContentPermissionSet)} is invalid"); + Guid IEntity.Key { get; set; } DateTime IEntity.CreateDate { get; set; } diff --git a/src/Umbraco.Core/Models/PropertyGroup.cs b/src/Umbraco.Abstractions/Models/PropertyGroup.cs similarity index 100% rename from src/Umbraco.Core/Models/PropertyGroup.cs rename to src/Umbraco.Abstractions/Models/PropertyGroup.cs diff --git a/src/Umbraco.Core/Models/PropertyGroupCollection.cs b/src/Umbraco.Abstractions/Models/PropertyGroupCollection.cs similarity index 98% rename from src/Umbraco.Core/Models/PropertyGroupCollection.cs rename to src/Umbraco.Abstractions/Models/PropertyGroupCollection.cs index 5422dfb792..f5b3012b1a 100644 --- a/src/Umbraco.Core/Models/PropertyGroupCollection.cs +++ b/src/Umbraco.Abstractions/Models/PropertyGroupCollection.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Models { private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim(); - internal PropertyGroupCollection() + public PropertyGroupCollection() { } public PropertyGroupCollection(IEnumerable groups) @@ -68,7 +68,7 @@ namespace Umbraco.Core.Models OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - internal new void Add(PropertyGroup item) + public new void Add(PropertyGroup item) { try { diff --git a/src/Umbraco.Core/Models/PropertyTypeCollection.cs b/src/Umbraco.Abstractions/Models/PropertyTypeCollection.cs similarity index 80% rename from src/Umbraco.Core/Models/PropertyTypeCollection.cs rename to src/Umbraco.Abstractions/Models/PropertyTypeCollection.cs index 6e41f0d12b..bca7e88e03 100644 --- a/src/Umbraco.Core/Models/PropertyTypeCollection.cs +++ b/src/Umbraco.Abstractions/Models/PropertyTypeCollection.cs @@ -8,24 +8,26 @@ using System.Threading; namespace Umbraco.Core.Models { + + //public interface IPropertyTypeCollection: IEnumerable /// - /// Represents a collection of objects. + /// Represents a collection of objects. /// [Serializable] [DataContract] // TODO: Change this to ObservableDictionary so we can reduce the INotifyCollectionChanged implementation details - public class PropertyTypeCollection : KeyedCollection, INotifyCollectionChanged, IDeepCloneable + public class PropertyTypeCollection : KeyedCollection, INotifyCollectionChanged, IDeepCloneable, ICollection { [IgnoreDataMember] private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim(); - internal PropertyTypeCollection(bool supportsPublishing) + public PropertyTypeCollection(bool supportsPublishing) { SupportsPublishing = supportsPublishing; } - public PropertyTypeCollection(bool supportsPublishing, IEnumerable properties) + public PropertyTypeCollection(bool supportsPublishing, IEnumerable properties) : this(supportsPublishing) { Reset(properties); @@ -34,25 +36,25 @@ namespace Umbraco.Core.Models public bool SupportsPublishing { get; } /// - /// Resets the collection to only contain the instances referenced in the parameter. + /// Resets the collection to only contain the instances referenced in the parameter. /// /// The properties. /// - internal void Reset(IEnumerable properties) + internal void Reset(IEnumerable properties) { //collection events will be raised in each of these calls Clear(); //collection events will be raised in each of these calls foreach (var property in properties) - Add(property); + Add(property); } - protected override void SetItem(int index, PropertyType item) + protected override void SetItem(int index, IPropertyType item) { item.SupportsPublishing = SupportsPublishing; var oldItem = index >= 0 ? this[index] : item; - base.SetItem(index, item); + base.SetItem(index, item); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem)); item.PropertyChanged += Item_PropertyChanged; } @@ -65,10 +67,10 @@ namespace Umbraco.Core.Models OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed)); } - protected override void InsertItem(int index, PropertyType item) + protected override void InsertItem(int index, IPropertyType item) { item.SupportsPublishing = SupportsPublishing; - base.InsertItem(index, item); + base.InsertItem(index, item); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); item.PropertyChanged += Item_PropertyChanged; } @@ -81,8 +83,9 @@ namespace Umbraco.Core.Models OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - // TODO: Instead of 'new' this should explicitly implement one of the collection interfaces members - internal new void Add(PropertyType item) + // 'new' keyword is required! we can explicitly implement ICollection.Add BUT since normally a concrete PropertyType type + // is passed in, the explicit implementation doesn't get called, this ensures it does get called. + public new void Add(IPropertyType item) { item.SupportsPublishing = SupportsPublishing; @@ -120,13 +123,13 @@ namespace Umbraco.Core.Models } /// - /// Occurs when a property changes on a PropertyType that exists in this collection + /// Occurs when a property changes on a IPropertyType that exists in this collection /// /// /// private void Item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - var propType = (PropertyType)sender; + var propType = (IPropertyType)sender; OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, propType, propType)); } @@ -156,7 +159,7 @@ namespace Umbraco.Core.Models return -1; } - protected override string GetKeyForItem(PropertyType item) + protected override string GetKeyForItem(IPropertyType item) { return item.Alias; } @@ -172,7 +175,7 @@ namespace Umbraco.Core.Models { var clone = new PropertyTypeCollection(SupportsPublishing); foreach (var propertyType in this) - clone.Add((PropertyType) propertyType.DeepClone()); + clone.Add((IPropertyType) propertyType.DeepClone()); return clone; } } diff --git a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs b/src/Umbraco.Abstractions/Models/UmbracoObjectTypes.cs similarity index 100% rename from src/Umbraco.Core/Models/UmbracoObjectTypes.cs rename to src/Umbraco.Abstractions/Models/UmbracoObjectTypes.cs diff --git a/src/Umbraco.Core/NameValueCollectionExtensions.cs b/src/Umbraco.Abstractions/NameValueCollectionExtensions.cs similarity index 95% rename from src/Umbraco.Core/NameValueCollectionExtensions.cs rename to src/Umbraco.Abstractions/NameValueCollectionExtensions.cs index 3c52989019..b7272c042d 100644 --- a/src/Umbraco.Core/NameValueCollectionExtensions.cs +++ b/src/Umbraco.Abstractions/NameValueCollectionExtensions.cs @@ -6,7 +6,7 @@ using System.Text; namespace Umbraco.Core { - internal static class NameValueCollectionExtensions + public static class NameValueCollectionExtensions { public static IEnumerable> AsEnumerable(this NameValueCollection nvc) { diff --git a/src/Umbraco.Abstractions/Properties/AssemblyInfo.cs b/src/Umbraco.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..6d5520f975 --- /dev/null +++ b/src/Umbraco.Abstractions/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: ComVisible(false)] +[assembly: Guid("DA322714-FB89-4943-92BD-BB122B82F66B")] + +// Umbraco Cms +[assembly: InternalsVisibleTo("Umbraco.Web")] +[assembly: InternalsVisibleTo("Umbraco.Web.UI")] +[assembly: InternalsVisibleTo("Umbraco.Examine")] +[assembly: InternalsVisibleTo("Umbraco.ModelsBuilder.Embedded")] + +[assembly: InternalsVisibleTo("Umbraco.Tests")] +[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")] + +// Allow this to be mocked in our unit tests +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] + +// Umbraco Deploy +[assembly: InternalsVisibleTo("Umbraco.Deploy")] +[assembly: InternalsVisibleTo("Umbraco.Deploy.UI")] +[assembly: InternalsVisibleTo("Umbraco.Deploy.Cloud")] + +// Umbraco Forms +[assembly: InternalsVisibleTo("Umbraco.Forms.Core")] +[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")] +[assembly: InternalsVisibleTo("Umbraco.Forms.Web")] + +// Umbraco Headless +[assembly: InternalsVisibleTo("Umbraco.Cloud.Headless")] + +// code analysis +// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")] diff --git a/src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs b/src/Umbraco.Abstractions/PropertyEditors/IIgnoreUserStartNodesConfig.cs similarity index 82% rename from src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs rename to src/Umbraco.Abstractions/PropertyEditors/IIgnoreUserStartNodesConfig.cs index bef3f42f46..28ce8654c3 100644 --- a/src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs +++ b/src/Umbraco.Abstractions/PropertyEditors/IIgnoreUserStartNodesConfig.cs @@ -3,7 +3,7 @@ /// /// Marker interface for any editor configuration that supports Ignoring user start nodes /// - internal interface IIgnoreUserStartNodesConfig + public interface IIgnoreUserStartNodesConfig { bool IgnoreUserStartNodes { get; set; } } diff --git a/src/Umbraco.Core/RegisterExtensions.cs b/src/Umbraco.Abstractions/RegisterExtensions.cs similarity index 100% rename from src/Umbraco.Core/RegisterExtensions.cs rename to src/Umbraco.Abstractions/RegisterExtensions.cs diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Abstractions/Services/IContentService.cs similarity index 99% rename from src/Umbraco.Core/Services/IContentService.cs rename to src/Umbraco.Abstractions/Services/IContentService.cs index c7f71d33fc..2a34fcb898 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Abstractions/Services/IContentService.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.ComponentModel; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Services diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Abstractions/Services/IEntityService.cs similarity index 99% rename from src/Umbraco.Core/Services/IEntityService.cs rename to src/Umbraco.Abstractions/Services/IEntityService.cs index f03bc640ec..2b2fad277a 100644 --- a/src/Umbraco.Core/Services/IEntityService.cs +++ b/src/Umbraco.Abstractions/Services/IEntityService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Services @@ -27,28 +26,28 @@ namespace Umbraco.Core.Services /// The identifier of the entity. /// The object type of the entity. IEntitySlim Get(int id, UmbracoObjectTypes objectType); - + /// /// Gets an entity. /// /// The unique key of the entity. /// The object type of the entity. IEntitySlim Get(Guid key, UmbracoObjectTypes objectType); - + /// /// Gets an entity. /// /// The type used to determine the object type of the entity. /// The identifier of the entity. IEntitySlim Get(int id) where T : IUmbracoEntity; - + /// /// Gets an entity. /// /// The type used to determine the object type of the entity. /// The unique key of the entity. IEntitySlim Get(Guid key) where T : IUmbracoEntity; - + /// /// Determines whether an entity exists. /// diff --git a/src/Umbraco.Core/Services/INotificationService.cs b/src/Umbraco.Abstractions/Services/INotificationService.cs similarity index 97% rename from src/Umbraco.Core/Services/INotificationService.cs rename to src/Umbraco.Abstractions/Services/INotificationService.cs index 1a48d73297..6ef639594d 100644 --- a/src/Umbraco.Core/Services/INotificationService.cs +++ b/src/Umbraco.Abstractions/Services/INotificationService.cs @@ -1,12 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence; namespace Umbraco.Core.Services { diff --git a/src/Umbraco.Core/Services/IPublicAccessService.cs b/src/Umbraco.Abstractions/Services/IPublicAccessService.cs similarity index 95% rename from src/Umbraco.Core/Services/IPublicAccessService.cs rename to src/Umbraco.Abstractions/Services/IPublicAccessService.cs index 6878e3f62d..a3efb07028 100644 --- a/src/Umbraco.Core/Services/IPublicAccessService.cs +++ b/src/Umbraco.Abstractions/Services/IPublicAccessService.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; +using System.Collections.Generic; using Umbraco.Core.Models; -using Umbraco.Core.Security; namespace Umbraco.Core.Services { diff --git a/src/Umbraco.Abstractions/Services/IRuntime.cs b/src/Umbraco.Abstractions/Services/IRuntime.cs index d433dde12d..e846342dbc 100644 --- a/src/Umbraco.Abstractions/Services/IRuntime.cs +++ b/src/Umbraco.Abstractions/Services/IRuntime.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; namespace Umbraco.Core { diff --git a/src/Umbraco.Core/Services/PublishResult.cs b/src/Umbraco.Abstractions/Services/PublishResult.cs similarity index 100% rename from src/Umbraco.Core/Services/PublishResult.cs rename to src/Umbraco.Abstractions/Services/PublishResult.cs diff --git a/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj b/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj index b3a1b4fa25..4fbb43e33d 100644 --- a/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj +++ b/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj @@ -4,6 +4,10 @@ netstandard2.0 7.3 Umbraco.Core + 9.0.0 + 9.0.0 + 9.0.0 + Umbraco CMS diff --git a/src/Umbraco.Core/Configuration/CaseInsensitiveEnumConfigConverter.cs b/src/Umbraco.Configuration/CaseInsensitiveEnumConfigConverter.cs similarity index 100% rename from src/Umbraco.Core/Configuration/CaseInsensitiveEnumConfigConverter.cs rename to src/Umbraco.Configuration/CaseInsensitiveEnumConfigConverter.cs diff --git a/src/Umbraco.Core/Configuration/CommaDelimitedConfigurationElement.cs b/src/Umbraco.Configuration/CommaDelimitedConfigurationElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/CommaDelimitedConfigurationElement.cs rename to src/Umbraco.Configuration/CommaDelimitedConfigurationElement.cs diff --git a/src/Umbraco.Configuration/ConfigsFactory.cs b/src/Umbraco.Configuration/ConfigsFactory.cs new file mode 100644 index 0000000000..c016c3171d --- /dev/null +++ b/src/Umbraco.Configuration/ConfigsFactory.cs @@ -0,0 +1,34 @@ +using System.Configuration; +using Umbraco.Core.Configuration.HealthChecks; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; + +namespace Umbraco.Core.Configuration +{ + public class ConfigsFactory : IConfigsFactory + { + private readonly IIOHelper _ioHelper; + + public ConfigsFactory(IIOHelper ioHelper) + { + _ioHelper = ioHelper; + GlobalSettings = new GlobalSettings(_ioHelper); + } + + public IGlobalSettings GlobalSettings { get; } + + public Configs Create() + { + var configs = new Configs(section => ConfigurationManager.GetSection(section)); + configs.Add(() => GlobalSettings); + + configs.Add("umbracoConfiguration/settings"); + configs.Add("umbracoConfiguration/HealthChecks"); + + configs.Add(() => new CoreDebug()); + configs.Add(() => new ConnectionStrings()); + configs.AddCoreConfigs(_ioHelper); + return configs; + } + } +} diff --git a/src/Umbraco.Configuration/ConnectionStrings.cs b/src/Umbraco.Configuration/ConnectionStrings.cs new file mode 100644 index 0000000000..1842ff6627 --- /dev/null +++ b/src/Umbraco.Configuration/ConnectionStrings.cs @@ -0,0 +1,21 @@ +using System; +using System.Configuration; +using System.Linq; +using System.Xml.Linq; +using Umbraco.Core.IO; + +namespace Umbraco.Core.Configuration +{ + public class ConnectionStrings : IConnectionStrings + { + public ConfigConnectionString this[string key] + { + get + { + var settings = ConfigurationManager.ConnectionStrings[key]; + + return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name); + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/CoreDebug.cs b/src/Umbraco.Configuration/CoreDebug.cs similarity index 53% rename from src/Umbraco.Core/Configuration/CoreDebug.cs rename to src/Umbraco.Configuration/CoreDebug.cs index b24e8a3329..0ff3274565 100644 --- a/src/Umbraco.Core/Configuration/CoreDebug.cs +++ b/src/Umbraco.Configuration/CoreDebug.cs @@ -1,22 +1,21 @@ using System; +using System.Configuration; namespace Umbraco.Core.Configuration { - internal class CoreDebug + public class CoreDebug : ICoreDebug { public CoreDebug() { - var appSettings = System.Configuration.ConfigurationManager.AppSettings; + var appSettings = ConfigurationManager.AppSettings; LogUncompletedScopes = string.Equals("true", appSettings[Constants.AppSettings.Debug.LogUncompletedScopes], StringComparison.OrdinalIgnoreCase); DumpOnTimeoutThreadAbort = string.Equals("true", appSettings[Constants.AppSettings.Debug.DumpOnTimeoutThreadAbort], StringComparison.OrdinalIgnoreCase); } - // when true, Scope logs the stack trace for any scope that gets disposed without being completed. - // this helps troubleshooting rogue scopes that we forget to complete + /// public bool LogUncompletedScopes { get; } - // when true, the Logger creates a mini dump of w3wp in ~/App_Data/MiniDump whenever it logs - // an error due to a ThreadAbortException that is due to a timeout. + /// public bool DumpOnTimeoutThreadAbort { get; } } } diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Configuration/GlobalSettings.cs similarity index 78% rename from src/Umbraco.Core/Configuration/GlobalSettings.cs rename to src/Umbraco.Configuration/GlobalSettings.cs index 1653760393..8ade096c4a 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Configuration/GlobalSettings.cs @@ -53,20 +53,42 @@ namespace Umbraco.Core.Configuration { ResetInternal(); } - - public static bool HasSmtpServerConfigured(string appPath) + public bool IsSmtpServerConfigured { - if (HasSmtpServer.HasValue) return HasSmtpServer.Value; + get + { + var smtpSection = ConfigurationManager.GetSection("system.net/mailSettings/smtp") as ConfigurationSection; + if (smtpSection is null) return false; - var config = WebConfigurationManager.OpenWebConfiguration(appPath); - var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings"); - // note: "noreply@example.com" is/was the sample SMTP from email - we'll regard that as "not configured" - if (settings == null || settings.Smtp == null || "noreply@example.com".Equals(settings.Smtp.From, StringComparison.OrdinalIgnoreCase)) return false; - if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false) - return true; - if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false) - return true; - return false; + var from = smtpSection.ElementInformation.Properties["from"]; + if (@from != null + && @from.Value is string fromPropValue + && string.IsNullOrEmpty(fromPropValue) == false + && !string.Equals("noreply@example.com", fromPropValue, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + var networkSection = ConfigurationManager.GetSection("system.net/mailSettings/smtp/network") as ConfigurationSection; + var host = networkSection?.ElementInformation.Properties["host"]; + if (host != null + && host.Value is string hostPropValue + && string.IsNullOrEmpty(hostPropValue) == false) + { + return true; + } + + var specifiedPickupDirectorySection = ConfigurationManager.GetSection("system.net/mailSettings/smtp/specifiedPickupDirectory") as ConfigurationSection; + var pickupDirectoryLocation = specifiedPickupDirectorySection?.ElementInformation.Properties["pickupDirectoryLocation"]; + if (pickupDirectoryLocation != null + && pickupDirectoryLocation.Value is string pickupDirectoryLocationPropValue + && string.IsNullOrEmpty(pickupDirectoryLocationPropValue) == false) + { + return true; + } + + return false; + } } /// @@ -166,7 +188,7 @@ namespace Umbraco.Core.Configuration } set { - SaveSetting(Constants.AppSettings.ConfigurationStatus, value); + SaveSetting(Constants.AppSettings.ConfigurationStatus, value, _ioHelper); } } @@ -175,9 +197,9 @@ namespace Umbraco.Core.Configuration /// /// Key of the setting to be saved. /// Value of the setting to be saved. - internal static void SaveSetting(string key, string value) + internal static void SaveSetting(string key, string value, IIOHelper ioHelper) { - var fileName = Current.IOHelper.MapPath(string.Format("{0}/web.config", Current.IOHelper.Root)); + var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root)); var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace); var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single(); @@ -197,9 +219,9 @@ namespace Umbraco.Core.Configuration /// Removes a setting from the configuration file. /// /// Key of the setting to be removed. - internal static void RemoveSetting(string key) + public static void RemoveSetting(string key, IIOHelper ioHelper) { - var fileName = Current.IOHelper.MapPath(string.Format("{0}/web.config", Current.IOHelper.Root)); + var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root)); var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace); var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single(); @@ -217,24 +239,25 @@ namespace Umbraco.Core.Configuration /// Gets a value indicating whether umbraco is running in [debug mode]. /// /// true if [debug mode]; otherwise, false. - public static bool DebugMode + public bool DebugMode { get { try { - if (HttpContext.Current != null) + if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection compilation) { - return HttpContext.Current.IsDebuggingEnabled; + var debugElement = compilation.ElementInformation.Properties["debug"]; + + return debugElement != null && (debugElement.Value is bool debug && debug); } - //go and get it from config directly - var section = ConfigurationManager.GetSection("system.web/compilation") as CompilationSection; - return section != null && section.Debug; } catch { - return false; + // ignored } + + return false; } } @@ -289,47 +312,6 @@ namespace Umbraco.Core.Configuration } } - /// - public string LocalTempPath - { - get - { - if (_localTempPath != null) - return _localTempPath; - - switch (LocalTempStorageLocation) - { - case LocalTempStorage.AspNetTemp: - return _localTempPath = System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData"); - - case LocalTempStorage.EnvironmentTemp: - - // environment temp is unique, we need a folder per site - - // use a hash - // combine site name and application id - // site name is a Guid on Cloud - // application id is eg /LM/W3SVC/123456/ROOT - // the combination is unique on one server - // and, if a site moves from worker A to B and then back to A... - // hopefully it gets a new Guid or new application id? - - var siteName = HostingEnvironment.SiteName; - var applicationId = HostingEnvironment.ApplicationID; // ie HttpRuntime.AppDomainAppId - - var hashString = siteName + "::" + applicationId; - var hash = hashString.GenerateHash(); - var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash); - - return _localTempPath = siteTemp; - - //case LocalTempStorage.Default: - //case LocalTempStorage.Unknown: - default: - return _localTempPath = _ioHelper.MapPath("~/App_Data/TEMP"); - } - } - } /// /// Gets the default UI language. @@ -397,6 +379,21 @@ namespace Umbraco.Core.Configuration private string _umbracoPath = null; public string UmbracoPath => GetterWithDefaultValue(Constants.AppSettings.UmbracoPath, "~/umbraco", ref _umbracoPath); + private bool _installMissingDatabase; + public bool InstallMissingDatabase => GetterWithDefaultValue("Umbraco.Core.RuntimeState.InstallMissingDatabase", false, ref _installMissingDatabase); + + private bool _installEmptyDatabase; + public bool InstallEmptyDatabase => GetterWithDefaultValue("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false, ref _installEmptyDatabase); + + private bool _disableElectionForSingleServer; + public bool DisableElectionForSingleServer => GetterWithDefaultValue(Constants.AppSettings.DisableElectionForSingleServer, false, ref _disableElectionForSingleServer); + + private string _registerType; + public string RegisterType => GetterWithDefaultValue(Constants.AppSettings.RegisterType, string.Empty, ref _registerType); + + private string _databaseFactoryServerVersion; + public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion); + private T GetterWithDefaultValue(string appSettingKey, T defaultValue, ref T backingField) { if (backingField != null) return backingField; diff --git a/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthCheckElement.cs b/src/Umbraco.Configuration/HealthChecks/DisabledHealthCheckElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthCheckElement.cs rename to src/Umbraco.Configuration/HealthChecks/DisabledHealthCheckElement.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs b/src/Umbraco.Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs rename to src/Umbraco.Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs b/src/Umbraco.Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs rename to src/Umbraco.Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/HealthChecksSection.cs b/src/Umbraco.Configuration/HealthChecks/HealthChecksSection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/HealthChecksSection.cs rename to src/Umbraco.Configuration/HealthChecks/HealthChecksSection.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodElement.cs b/src/Umbraco.Configuration/HealthChecks/NotificationMethodElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodElement.cs rename to src/Umbraco.Configuration/HealthChecks/NotificationMethodElement.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElement.cs b/src/Umbraco.Configuration/HealthChecks/NotificationMethodSettingsElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElement.cs rename to src/Umbraco.Configuration/HealthChecks/NotificationMethodSettingsElement.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs b/src/Umbraco.Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs rename to src/Umbraco.Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodsElementCollection.cs b/src/Umbraco.Configuration/HealthChecks/NotificationMethodsElementCollection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodsElementCollection.cs rename to src/Umbraco.Configuration/HealthChecks/NotificationMethodsElementCollection.cs diff --git a/src/Umbraco.Core/Configuration/InnerTextConfigurationElement.cs b/src/Umbraco.Configuration/InnerTextConfigurationElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/InnerTextConfigurationElement.cs rename to src/Umbraco.Configuration/InnerTextConfigurationElement.cs diff --git a/src/Umbraco.Core/Configuration/OptionalCommaDelimitedConfigurationElement.cs b/src/Umbraco.Configuration/OptionalCommaDelimitedConfigurationElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/OptionalCommaDelimitedConfigurationElement.cs rename to src/Umbraco.Configuration/OptionalCommaDelimitedConfigurationElement.cs diff --git a/src/Umbraco.Core/Configuration/OptionalInnerTextConfigurationElement.cs b/src/Umbraco.Configuration/OptionalInnerTextConfigurationElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/OptionalInnerTextConfigurationElement.cs rename to src/Umbraco.Configuration/OptionalInnerTextConfigurationElement.cs diff --git a/src/Umbraco.Configuration/Properties/AssemblyInfo.cs b/src/Umbraco.Configuration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d10dd929da --- /dev/null +++ b/src/Umbraco.Configuration/Properties/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Umbraco Cms +[assembly: InternalsVisibleTo("Umbraco.Tests")] +[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")] + +// Allow this to be mocked in our unit tests +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] diff --git a/src/Umbraco.Core/Configuration/RawXmlConfigurationElement.cs b/src/Umbraco.Configuration/RawXmlConfigurationElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/RawXmlConfigurationElement.cs rename to src/Umbraco.Configuration/RawXmlConfigurationElement.cs diff --git a/src/Umbraco.Configuration/Umbraco.Configuration.csproj b/src/Umbraco.Configuration/Umbraco.Configuration.csproj new file mode 100644 index 0000000000..04f8eb14d3 --- /dev/null +++ b/src/Umbraco.Configuration/Umbraco.Configuration.csproj @@ -0,0 +1,39 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + <_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" /> + <_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" /> + <_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" /> + + + + + + + + + + + + + C:\Users\Bjarke\AppData\Local\Temp\Temporary ASP.NET Files\root\408beac9\de517473\assembly\dl3\77bf709f\48ac59e4_3595d501\Umbraco.Core.dll + + + + diff --git a/src/Umbraco.Core/Configuration/UmbracoConfigurationSection.cs b/src/Umbraco.Configuration/UmbracoConfigurationSection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoConfigurationSection.cs rename to src/Umbraco.Configuration/UmbracoConfigurationSection.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/BackOfficeElement.cs b/src/Umbraco.Configuration/UmbracoSettings/BackOfficeElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/BackOfficeElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/BackOfficeElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CharCollection.cs b/src/Umbraco.Configuration/UmbracoSettings/CharCollection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/CharCollection.cs rename to src/Umbraco.Configuration/UmbracoSettings/CharCollection.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CharElement.cs b/src/Umbraco.Configuration/UmbracoSettings/CharElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/CharElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/CharElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs similarity index 99% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs index 77ad7df0dc..8e4f0edd8f 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs @@ -33,7 +33,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings [ConfigurationProperty("allowedUploadFiles")] internal CommaDelimitedConfigurationElement AllowedUploadFiles => GetOptionalDelimitedElement("allowedUploadFiles", new string[0]); - + [ConfigurationProperty("showDeprecatedPropertyEditors")] internal InnerTextConfigurationElement ShowDeprecatedPropertyEditors => GetOptionalTextElement("showDeprecatedPropertyEditors", false); diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentError404Collection.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentError404Collection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ContentError404Collection.cs rename to src/Umbraco.Configuration/UmbracoSettings/ContentError404Collection.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorPageElement.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentErrorPageElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorPageElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/ContentErrorPageElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorsElement.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentErrorsElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorsElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/ContentErrorsElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingElement.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentImagingElement.cs similarity index 93% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/ContentImagingElement.cs index 67562c411a..9a5a9b2a59 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingElement.cs +++ b/src/Umbraco.Configuration/UmbracoSettings/ContentImagingElement.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings //set the default GetDefaultImageFileTypes()); - internal static string[] GetDefaultImageFileTypes() + public static string[] GetDefaultImageFileTypes() { return new[] {"jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif"}; } @@ -49,7 +49,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings } } - internal static ImagingAutoFillPropertiesCollection GetDefaultImageAutoFillProperties() + public static ImagingAutoFillPropertiesCollection GetDefaultImageAutoFillProperties() { return new ImagingAutoFillPropertiesCollection { diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentSectionExtensions.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs rename to src/Umbraco.Configuration/UmbracoSettings/ContentSectionExtensions.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ImagingAutoFillPropertiesCollection.cs b/src/Umbraco.Configuration/UmbracoSettings/ImagingAutoFillPropertiesCollection.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ImagingAutoFillPropertiesCollection.cs rename to src/Umbraco.Configuration/UmbracoSettings/ImagingAutoFillPropertiesCollection.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ImagingAutoFillUploadFieldElement.cs b/src/Umbraco.Configuration/UmbracoSettings/ImagingAutoFillUploadFieldElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/ImagingAutoFillUploadFieldElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/ImagingAutoFillUploadFieldElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/LoggingElement.cs b/src/Umbraco.Configuration/UmbracoSettings/LoggingElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/LoggingElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/LoggingElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/NotificationsElement.cs b/src/Umbraco.Configuration/UmbracoSettings/NotificationsElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/NotificationsElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/NotificationsElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs b/src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs similarity index 98% rename from src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs index 263a822381..80fcb6ca1a 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs +++ b/src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs @@ -38,7 +38,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings } } - internal static CharCollection GetDefaultCharReplacements() + public static CharCollection GetDefaultCharReplacements() { var dictionary = new Dictionary() { diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/SecurityElement.cs b/src/Umbraco.Configuration/UmbracoSettings/SecurityElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/SecurityElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/SecurityElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/TourConfigElement.cs b/src/Umbraco.Configuration/UmbracoSettings/TourConfigElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/TourConfigElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/TourConfigElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoConfigurationElement.cs b/src/Umbraco.Configuration/UmbracoSettings/UmbracoConfigurationElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoConfigurationElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/UmbracoConfigurationElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs b/src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs similarity index 58% rename from src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs rename to src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs index 7cf8096345..98fdcaff93 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs +++ b/src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs @@ -2,26 +2,26 @@ namespace Umbraco.Core.Configuration.UmbracoSettings { - public class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection + internal class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection { [ConfigurationProperty("backOffice")] - internal BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"]; + public BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"]; [ConfigurationProperty("content")] - internal ContentElement Content => (ContentElement)this["content"]; + public ContentElement Content => (ContentElement)this["content"]; [ConfigurationProperty("security")] - internal SecurityElement Security => (SecurityElement)this["security"]; + public SecurityElement Security => (SecurityElement)this["security"]; [ConfigurationProperty("requestHandler")] - internal RequestHandlerElement RequestHandler => (RequestHandlerElement)this["requestHandler"]; + public RequestHandlerElement RequestHandler => (RequestHandlerElement)this["requestHandler"]; [ConfigurationProperty("logging")] - internal LoggingElement Logging => (LoggingElement)this["logging"]; + public LoggingElement Logging => (LoggingElement)this["logging"]; [ConfigurationProperty("web.routing")] - internal WebRoutingElement WebRouting => (WebRoutingElement)this["web.routing"]; + public WebRoutingElement WebRouting => (WebRoutingElement)this["web.routing"]; IContentSection IUmbracoSettingsSection.Content => Content; diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs b/src/Umbraco.Configuration/UmbracoSettings/UrlReplacingElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/UrlReplacingElement.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/WebRoutingElement.cs b/src/Umbraco.Configuration/UmbracoSettings/WebRoutingElement.cs similarity index 100% rename from src/Umbraco.Core/Configuration/UmbracoSettings/WebRoutingElement.cs rename to src/Umbraco.Configuration/UmbracoSettings/WebRoutingElement.cs diff --git a/src/Umbraco.Configuration/UmbracoVersionExtensions.cs b/src/Umbraco.Configuration/UmbracoVersionExtensions.cs new file mode 100644 index 0000000000..168bb16f57 --- /dev/null +++ b/src/Umbraco.Configuration/UmbracoVersionExtensions.cs @@ -0,0 +1,33 @@ +using System.Configuration; +using Semver; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration +{ + public static class UmbracoVersionExtensions + { + /// + /// Gets the "local" version of the site. + /// + /// + /// Three things have a version, really: the executing code, the database model, + /// and the site/files. The database model version is entirely managed via migrations, + /// and changes during an upgrade. The executing code version changes when new code is + /// deployed. The site/files version changes during an upgrade. + /// + public static SemVersion LocalVersion(this IUmbracoVersion umbracoVersion) + { + try + { + // TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings + var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus]; + return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null; + } + catch + { + return null; + } + } + } +} diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index afc2a93ea0..3661695c54 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -61,7 +61,7 @@ namespace Umbraco.Core.Composing } } - internal static bool HasFactory => _factory != null; + public static bool HasFactory => _factory != null; /// /// Resets . Indented for testing only, and not supported in production code. @@ -93,11 +93,11 @@ namespace Umbraco.Core.Composing /// Unlocks so that it is possible to add configurations /// directly to without having to wire composition. /// - public static void UnlockConfigs() + public static void UnlockConfigs(IConfigsFactory configsFactory) { if (_factory != null) throw new InvalidOperationException("Cannot unlock configs when a factory has been set."); - _configs = new Configs(); + _configs = configsFactory.Create(); } internal static event EventHandler Resetted; @@ -113,7 +113,7 @@ namespace Umbraco.Core.Composing public static ILogger Logger => _logger ?? (_logger = _factory?.TryGetInstance() - ?? new DebugDiagnosticsLogger()); + ?? new DebugDiagnosticsLogger(new MessageTemplates())); public static IProfiler Profiler => _profiler ?? (_profiler = _factory?.TryGetInstance() @@ -207,6 +207,9 @@ namespace Umbraco.Core.Composing public static readonly IIOHelper IOHelper = Umbraco.Core.IO.IOHelper.Default; + public static IUmbracoVersion UmbracoVersion + => Factory.GetInstance(); + #endregion } } diff --git a/src/Umbraco.Core/Composing/RegisterFactory.cs b/src/Umbraco.Core/Composing/RegisterFactory.cs index ea25d6a135..8f842e14fe 100644 --- a/src/Umbraco.Core/Composing/RegisterFactory.cs +++ b/src/Umbraco.Core/Composing/RegisterFactory.cs @@ -1,6 +1,6 @@ using System; -using System.Configuration; using System.Reflection; +using Umbraco.Core.Configuration; namespace Umbraco.Core.Composing { @@ -21,11 +21,11 @@ namespace Umbraco.Core.Composing /// To override the default LightInjectContainer, add an appSetting named 'Umbraco.Core.RegisterType' with /// a fully qualified type name to a class with a static method "Create" returning an IRegister. /// - public static IRegister Create() + public static IRegister Create(IGlobalSettings globalSettings) { Type type; - var configuredTypeName = ConfigurationManager.AppSettings[Constants.AppSettings.RegisterType]; + var configuredTypeName = globalSettings.RegisterType; if (configuredTypeName.IsNullOrWhiteSpace()) { // try to get the web LightInject container type, diff --git a/src/Umbraco.Core/CompositionExtensions_Essentials.cs b/src/Umbraco.Core/CompositionExtensions_Essentials.cs index 20c1646629..3174f07468 100644 --- a/src/Umbraco.Core/CompositionExtensions_Essentials.cs +++ b/src/Umbraco.Core/CompositionExtensions_Essentials.cs @@ -1,5 +1,6 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -22,7 +23,8 @@ namespace Umbraco.Core TypeLoader typeLoader, IRuntimeState state, ITypeFinder typeFinder, - IIOHelper ioHelper) + IIOHelper ioHelper, + IUmbracoVersion umbracoVersion) { composition.RegisterUnique(logger); composition.RegisterUnique(profiler); @@ -35,6 +37,7 @@ namespace Umbraco.Core composition.RegisterUnique(state); composition.RegisterUnique(typeFinder); composition.RegisterUnique(ioHelper); + composition.RegisterUnique(umbracoVersion); } } } diff --git a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs index 5c45b41f43..65b1a0d9ea 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs @@ -1,51 +1,56 @@ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading; using System.Web; -using System.Web.Routing; -using Umbraco.Core.Composing; +using System.Web.Hosting; using Umbraco.Core.IO; namespace Umbraco.Core.Configuration { + public static class GlobalSettingsExtensions { - private static string _mvcArea; - + private static string _localTempPath; /// - /// This returns the string of the MVC Area route. + /// Gets the location of temporary files. /// - /// - /// This will return the MVC area that we will route all custom routes through like surface controllers, etc... - /// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin - /// we will convert the '/' to '-' and use that as the path. its a bit lame but will work. - /// - /// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something - /// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco". - /// - public static string GetUmbracoMvcArea(this IGlobalSettings globalSettings) + public static string LocalTempPath(this IGlobalSettings globalSettings, IIOHelper ioHelper) { - if (_mvcArea != null) return _mvcArea; - _mvcArea = GetUmbracoMvcAreaNoCache(globalSettings); + if (_localTempPath != null) + return _localTempPath; - return _mvcArea; - } - - internal static string GetUmbracoMvcAreaNoCache(this IGlobalSettings globalSettings) - { - if (globalSettings.Path.IsNullOrWhiteSpace()) + switch (globalSettings.LocalTempStorageLocation) { - throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified"); + case LocalTempStorage.AspNetTemp: + return _localTempPath = System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData"); + + case LocalTempStorage.EnvironmentTemp: + + // environment temp is unique, we need a folder per site + + // use a hash + // combine site name and application id + // site name is a Guid on Cloud + // application id is eg /LM/W3SVC/123456/ROOT + // the combination is unique on one server + // and, if a site moves from worker A to B and then back to A... + // hopefully it gets a new Guid or new application id? + + var siteName = HostingEnvironment.SiteName; + var applicationId = HostingEnvironment.ApplicationID; // ie HttpRuntime.AppDomainAppId + + var hashString = siteName + "::" + applicationId; + var hash = hashString.GenerateHash(); + var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash); + + return _localTempPath = siteTemp; + + //case LocalTempStorage.Default: + //case LocalTempStorage.Unknown: + default: + return _localTempPath = ioHelper.MapPath("~/App_Data/TEMP"); } - var path = globalSettings.Path; - if (path.StartsWith(Current.IOHelper.Root)) // beware of TrimStart, see U4-2518 - path = path.Substring(Current.IOHelper.Root.Length); - return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower(); } } diff --git a/src/Umbraco.Core/ConventionsHelper.cs b/src/Umbraco.Core/ConventionsHelper.cs index 16ad95b95e..834078f84d 100644 --- a/src/Umbraco.Core/ConventionsHelper.cs +++ b/src/Umbraco.Core/ConventionsHelper.cs @@ -21,7 +21,8 @@ namespace Umbraco.Core new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Integer, true, Constants.Conventions.Member.FailedPasswordAttempts) { - Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel + Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, + DataTypeId = Constants.DataTypes.LabelInt } }, { @@ -45,7 +46,8 @@ namespace Umbraco.Core new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Date, true, Constants.Conventions.Member.LastLockoutDate) { - Name = Constants.Conventions.Member.LastLockoutDateLabel + Name = Constants.Conventions.Member.LastLockoutDateLabel, + DataTypeId = Constants.DataTypes.LabelDateTime } }, { @@ -53,7 +55,8 @@ namespace Umbraco.Core new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Date, true, Constants.Conventions.Member.LastLoginDate) { - Name = Constants.Conventions.Member.LastLoginDateLabel + Name = Constants.Conventions.Member.LastLoginDateLabel, + DataTypeId = Constants.DataTypes.LabelDateTime } }, { @@ -61,7 +64,8 @@ namespace Umbraco.Core new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Date, true, Constants.Conventions.Member.LastPasswordChangeDate) { - Name = Constants.Conventions.Member.LastPasswordChangeDateLabel + Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, + DataTypeId = Constants.DataTypes.LabelDateTime } }, { @@ -69,7 +73,8 @@ namespace Umbraco.Core new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, Constants.Conventions.Member.PasswordAnswer) { - Name = Constants.Conventions.Member.PasswordAnswerLabel + Name = Constants.Conventions.Member.PasswordAnswerLabel, + DataTypeId = Constants.DataTypes.LabelString } }, { @@ -77,7 +82,8 @@ namespace Umbraco.Core new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, Constants.Conventions.Member.PasswordQuestion) { - Name = Constants.Conventions.Member.PasswordQuestionLabel + Name = Constants.Conventions.Member.PasswordQuestionLabel, + DataTypeId = Constants.DataTypes.LabelString } } }; diff --git a/src/Umbraco.Core/EmailSender.cs b/src/Umbraco.Core/EmailSender.cs index e876d5b0c8..7dc75b116d 100644 --- a/src/Umbraco.Core/EmailSender.cs +++ b/src/Umbraco.Core/EmailSender.cs @@ -2,6 +2,7 @@ using System.Net.Mail; using System.Threading.Tasks; using System.Web; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Events; @@ -28,7 +29,7 @@ namespace Umbraco.Core _enableEvents = enableEvents; } - private static readonly Lazy SmtpConfigured = new Lazy(() => GlobalSettings.HasSmtpServerConfigured(HttpRuntime.AppDomainAppVirtualPath)); + private static readonly Lazy SmtpConfigured = new Lazy(() => Current.Configs.Global().IsSmtpServerConfigured); /// /// Sends the message non-async diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index c4fa57dd28..0c15ac1b26 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -115,8 +115,6 @@ namespace Umbraco.Core.IO return MapPath(path, true); } - - /// /// Verifies that the current filepath matches a directory where the user is allowed to edit a file. /// diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index d2d04204a1..b77b6293fd 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -1,15 +1,12 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.IO; using System.Linq; using System.Threading.Tasks; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; -using Umbraco.Core.Media; using Umbraco.Core.Models; namespace Umbraco.Core.IO diff --git a/src/Umbraco.Core/IO/SystemFiles.cs b/src/Umbraco.Core/IO/SystemFiles.cs index 132945d130..5025a5b01f 100644 --- a/src/Umbraco.Core/IO/SystemFiles.cs +++ b/src/Umbraco.Core/IO/SystemFiles.cs @@ -11,7 +11,7 @@ namespace Umbraco.Core.IO // TODO: Kill this off we don't have umbraco.config XML cache we now have NuCache public static string GetContentCacheXml(IGlobalSettings globalSettings) { - return Path.Combine(globalSettings.LocalTempPath, "umbraco.config"); + return Path.Combine(globalSettings.LocalTempPath(Current.IOHelper), "umbraco.config"); } } } diff --git a/src/Umbraco.Core/Logging/MessageTemplates.cs b/src/Umbraco.Core/Logging/MessageTemplates.cs index 47de1230ff..4640007e1a 100644 --- a/src/Umbraco.Core/Logging/MessageTemplates.cs +++ b/src/Umbraco.Core/Logging/MessageTemplates.cs @@ -8,10 +8,7 @@ using Serilog.Parsing; namespace Umbraco.Core.Logging { - /// - /// Provides tools to support message templates. - /// - public static class MessageTemplates + public class MessageTemplates : IMessageTemplates { // Umbraco now uses Message Templates (https://messagetemplates.org/) for logging, which means // we cannot plainly use string.Format() to format them. There is a work-in-progress C# lib, @@ -21,7 +18,7 @@ namespace Umbraco.Core.Logging private static readonly Lazy MinimalLogger = new Lazy(() => new LoggerConfiguration().CreateLogger()); - public static string Render(string messageTemplate, params object[] args) + public string Render(string messageTemplate, params object[] args) { // by default, unless initialized otherwise, Log.Logger is SilentLogger which cannot bind message // templates. Log.Logger is set to a true Logger when initializing Umbraco's logger, but in case diff --git a/src/Umbraco.Core/Manifest/IPackageManifest.cs b/src/Umbraco.Core/Manifest/IPackageManifest.cs new file mode 100644 index 0000000000..01b0be70db --- /dev/null +++ b/src/Umbraco.Core/Manifest/IPackageManifest.cs @@ -0,0 +1,65 @@ +using System.Runtime.Serialization; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Core.Manifest +{ + public interface IPackageManifest + { + /// + /// Gets the source path of the manifest. + /// + /// + /// Gets the full absolute file path of the manifest, + /// using system directory separators. + /// + string Source { get; set; } + + /// + /// Gets or sets the scripts listed in the manifest. + /// + [DataMember(Name = "javascript")] + string[] Scripts { get; set; } + + /// + /// Gets or sets the stylesheets listed in the manifest. + /// + [DataMember(Name = "css")] + string[] Stylesheets { get; set; } + + /// + /// Gets or sets the property editors listed in the manifest. + /// + [DataMember(Name = "propertyEditors")] + IDataEditor[] PropertyEditors { get; set; } + + /// + /// Gets or sets the parameter editors listed in the manifest. + /// + [DataMember(Name = "parameterEditors")] + IDataEditor[] ParameterEditors { get; set; } + + /// + /// Gets or sets the grid editors listed in the manifest. + /// + [DataMember(Name = "gridEditors")] + GridEditor[] GridEditors { get; set; } + + /// + /// Gets or sets the content apps listed in the manifest. + /// + [DataMember(Name = "contentApps")] + ManifestContentAppDefinition[] ContentApps { get; set; } + + /// + /// Gets or sets the dashboards listed in the manifest. + /// + [DataMember(Name = "dashboards")] + ManifestDashboard[] Dashboards { get; set; } + + /// + /// Gets or sets the sections listed in the manifest. + /// + [DataMember(Name = "sections")] + ManifestSection[] Sections { get; set; } + } +} diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs index 9f62e8c355..af39b6c7c5 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs @@ -1,5 +1,4 @@ using System; -using System.Configuration; using System.Data.SqlServerCe; using System.IO; using System.Linq; @@ -7,7 +6,6 @@ using System.Xml.Linq; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; @@ -340,35 +338,6 @@ namespace Umbraco.Core.Migrations.Install attribute.Value = value; } - internal bool IsConnectionStringConfigured(ConnectionStringSettings databaseSettings) - { - var dbIsSqlCe = false; - if (databaseSettings?.ProviderName != null) - dbIsSqlCe = databaseSettings.ProviderName == Constants.DbProviderNames.SqlCe; - var sqlCeDatabaseExists = false; - if (dbIsSqlCe) - { - var parts = databaseSettings.ConnectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - var dataSourcePart = parts.FirstOrDefault(x => x.InvariantStartsWith("Data Source=")); - if (dataSourcePart != null) - { - var datasource = dataSourcePart.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()); - var filePath = datasource.Replace("Data Source=", string.Empty); - sqlCeDatabaseExists = File.Exists(filePath); - } - } - - // Either the connection details are not fully specified or it's a SQL CE database that doesn't exist yet - if (databaseSettings == null - || string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) || string.IsNullOrWhiteSpace(databaseSettings.ProviderName) - || (dbIsSqlCe && sqlCeDatabaseExists == false)) - { - return false; - } - - return true; - } - #endregion #region Database Schema diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index e8fd3414ec..070f4bdf6a 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -1,6 +1,6 @@ using System; -using System.Configuration; using Semver; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Migrations.Upgrade.Common; using Umbraco.Core.Migrations.Upgrade.V_8_0_0; @@ -17,6 +17,7 @@ namespace Umbraco.Core.Migrations.Upgrade private const string InitPrefix = "{init-"; private const string InitSuffix = "}"; + private IUmbracoVersion UmbracoVersion => Current.UmbracoVersion; /// /// Initializes a new instance of the class. /// @@ -61,7 +62,7 @@ namespace Umbraco.Core.Migrations.Upgrade get { // no state in database yet - assume we have something in web.config that makes some sense - if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var currentVersion)) + if (!SemVersion.TryParse(Current.Configs.Global().ConfigurationStatus, out var currentVersion)) throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting."); // cannot go back in time diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index c87cb0a370..e5adddad72 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Models private int _writerId; private IPropertyCollection _properties; private ContentCultureInfosCollection _cultureInfos; - internal IReadOnlyList AllPropertyTypes { get; } + internal IReadOnlyList AllPropertyTypes { get; } #region Used for change tracking @@ -78,7 +78,7 @@ namespace Umbraco.Core.Models //track all property types on this content type, these can never change during the lifetime of this single instance //there is no real extra memory overhead of doing this since these property types are already cached on this object via the //properties already. - AllPropertyTypes = new List(contentType.CompositionPropertyTypes); + AllPropertyTypes = new List(contentType.CompositionPropertyTypes); } [IgnoreDataMember] diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 04bcb7424a..a42419c66a 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -107,7 +107,7 @@ namespace Umbraco.Core.Models // { // var newAliases = string.Join(", ", e.NewItems.Cast().Select(x => x.Alias)); // throw new InvalidOperationException($"Other property types already exist with the aliases: {newAliases}"); - // } + // } //} OnPropertyChanged(nameof(PropertyTypes)); @@ -246,7 +246,7 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] [DoNotClone] - public IEnumerable PropertyTypes + public IEnumerable PropertyTypes { get { @@ -256,7 +256,7 @@ namespace Umbraco.Core.Models /// [DoNotClone] - public IEnumerable NoGroupPropertyTypes + public IEnumerable NoGroupPropertyTypes { get => _noGroupPropertyTypes; set @@ -305,17 +305,17 @@ namespace Umbraco.Core.Models /// /// Adds a PropertyType to a specific PropertyGroup /// - /// to add + /// to add /// Name of the PropertyGroup to add the PropertyType to /// Returns True if PropertyType was added, otherwise False - public abstract bool AddPropertyType(PropertyType propertyType, string propertyGroupName); + public abstract bool AddPropertyType(IPropertyType propertyType, string propertyGroupName); /// /// Adds a PropertyType, which does not belong to a PropertyGroup. /// - /// to add + /// to add /// Returns True if PropertyType was added, otherwise False - public bool AddPropertyType(PropertyType propertyType) + public bool AddPropertyType(IPropertyType propertyType) { if (PropertyTypeExists(propertyType.Alias) == false) { @@ -365,7 +365,7 @@ namespace Umbraco.Core.Models /// /// Removes a PropertyType from the current ContentType /// - /// Alias of the to remove + /// Alias of the to remove public void RemovePropertyType(string propertyTypeAlias) { //check through each property group to see if we can remove the property type by alias from it diff --git a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs index 51c642c20d..121fb7a5d1 100644 --- a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs +++ b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs @@ -44,16 +44,13 @@ namespace Umbraco.Core.Models // property variation change? var hasAnyPropertyVariationChanged = contentType.PropertyTypes.Any(propertyType => { - if (!(propertyType is IRememberBeingDirty dirtyProperty)) - throw new Exception("oops"); - // skip new properties // TODO: This used to be WasPropertyDirty("HasIdentity") but i don't think that actually worked for detecting new entities this does seem to work properly - var isNewProperty = dirtyProperty.WasPropertyDirty("Id"); + var isNewProperty = propertyType.WasPropertyDirty("Id"); if (isNewProperty) return false; // variation change? - var dirty = dirtyProperty.WasPropertyDirty("Variations"); + var dirty = propertyType.WasPropertyDirty("Variations"); if (dirty) a.Add(propertyType.Alias); diff --git a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs index ff61a15979..9db0eb9b41 100644 --- a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs @@ -56,7 +56,7 @@ namespace Umbraco.Core.Models // any change to compositions are ignored and that breaks many things - and tracking // changes to refresh the cache would be expensive. - void AcquireProperty(PropertyType propertyType) + void AcquireProperty(IPropertyType propertyType) { propertyType.Variations = propertyType.Variations & Variations; propertyType.ResetDirtyProperties(false); @@ -76,7 +76,7 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] - public IEnumerable CompositionPropertyTypes + public IEnumerable CompositionPropertyTypes { get { @@ -85,9 +85,9 @@ namespace Umbraco.Core.Models // // see note in CompositionPropertyGroups for comments on caching the resulting enumerable - PropertyType AcquireProperty(PropertyType propertyType) + IPropertyType AcquireProperty(IPropertyType propertyType) { - propertyType = (PropertyType) propertyType.DeepClone(); + propertyType = (IPropertyType) propertyType.DeepClone(); propertyType.Variations = propertyType.Variations & Variations; propertyType.ResetDirtyProperties(false); return propertyType; @@ -107,9 +107,9 @@ namespace Umbraco.Core.Models /// Gets them raw, ie with their original variation. /// [IgnoreDataMember] - internal IEnumerable RawComposedPropertyTypes => GetRawComposedPropertyTypes(); + internal IEnumerable RawComposedPropertyTypes => GetRawComposedPropertyTypes(); - private IEnumerable GetRawComposedPropertyTypes(bool start = true) + private IEnumerable GetRawComposedPropertyTypes(bool start = true) { var propertyTypes = ContentTypeComposition .Cast() @@ -250,10 +250,10 @@ namespace Umbraco.Core.Models /// /// Adds a PropertyType to a specific PropertyGroup /// - /// to add + /// to add /// Name of the PropertyGroup to add the PropertyType to /// Returns True if PropertyType was added, otherwise False - public override bool AddPropertyType(PropertyType propertyType, string propertyGroupName) + public override bool AddPropertyType(IPropertyType propertyType, string propertyGroupName) { // ensure no duplicate alias - over all composition properties if (PropertyTypeExists(propertyType.Alias)) @@ -302,7 +302,7 @@ namespace Umbraco.Core.Models base.PerformDeepClone(clone); var clonedEntity = (ContentTypeCompositionBase)clone; - + //need to manually assign since this is an internal field and will not be automatically mapped clonedEntity.RemovedContentTypeKeyTracker = new List(); clonedEntity._contentTypeComposition = ContentTypeComposition.Select(x => (IContentTypeComposition)x.DeepClone()).ToList(); diff --git a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs index 8dc056d555..7e42a526b0 100644 --- a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.ComponentModel; using System.Linq; using Umbraco.Core.Composing; using Umbraco.Core.Models.Entities; @@ -403,6 +404,18 @@ namespace Umbraco.Core.Models.Identity _beingDirty.EnableChangeTracking(); } + public event PropertyChangedEventHandler PropertyChanged + { + add + { + _beingDirty.PropertyChanged += value; + } + remove + { + _beingDirty.PropertyChanged -= value; + } + } + #endregion //Custom comparer for enumerables @@ -413,5 +426,6 @@ namespace Umbraco.Core.Models.Identity private static readonly DelegateEqualityComparer StartIdsComparer = new DelegateEqualityComparer( (groups, enumerable) => groups.UnsortedSequenceEqual(enumerable), groups => groups.GetHashCode()); + } } diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 070d0773d2..e12a722b37 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Runtime.Serialization; +using Umbraco.Core.Composing; namespace Umbraco.Core.Models.Packaging { @@ -69,8 +70,8 @@ namespace Umbraco.Core.Models.Packaging /// The minimum umbraco version that this package requires /// [DataMember(Name = "umbracoVersion")] - public Version UmbracoVersion { get; set; } = Configuration.UmbracoVersion.Current; - + public Version UmbracoVersion { get; set; } = Current.UmbracoVersion.Current; + [DataMember(Name = "author")] [Required] public string Author { get; set; } = string.Empty; @@ -131,7 +132,7 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } = string.Empty; - + } diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs index 9aa9ab4d74..36efbad404 100644 --- a/src/Umbraco.Core/Models/Property.cs +++ b/src/Umbraco.Core/Models/Property.cs @@ -47,6 +47,54 @@ namespace Umbraco.Core.Models PropertyType = propertyType; } + /// + /// Creates a new instance for existing + /// + /// + /// + /// + /// Generally will contain a published and an unpublished property values + /// + /// + public static Property CreateWithValues(int id, IPropertyType propertyType, params InitialPropertyValue[] values) + { + var property = new Property(propertyType); + try + { + property.DisableChangeTracking(); + property.Id = id; + foreach(var value in values) + { + property.FactorySetValue(value.Culture, value.Segment, value.Published, value.Value); + } + property.ResetDirtyProperties(false); + return property; + } + finally + { + property.EnableChangeTracking(); + } + } + + /// + /// Used for constructing a new instance + /// + public class InitialPropertyValue + { + public InitialPropertyValue(string culture, string segment, bool published, object value) + { + Culture = culture; + Segment = segment; + Published = published; + Value = value; + } + + public string Culture { get; } + public string Segment { get; } + public bool Published { get; } + public object Value { get; } + } + /// /// Represents a property value. /// @@ -247,7 +295,7 @@ namespace Umbraco.Core.Models if (!PropertyType.SupportsPublishing) throw new NotSupportedException("Property type does not support publishing."); var origValue = pvalue.PublishedValue; - pvalue.PublishedValue = PropertyType.ConvertAssignedValue(pvalue.EditedValue); + pvalue.PublishedValue = ConvertAssignedValue(pvalue.EditedValue); DetectChanges(pvalue.EditedValue, origValue, nameof(Values), PropertyValueComparer, false); } @@ -258,7 +306,7 @@ namespace Umbraco.Core.Models if (!PropertyType.SupportsPublishing) throw new NotSupportedException("Property type does not support publishing."); var origValue = pvalue.PublishedValue; - pvalue.PublishedValue = PropertyType.ConvertAssignedValue(null); + pvalue.PublishedValue = ConvertAssignedValue(null); DetectChanges(pvalue.EditedValue, origValue, nameof(Values), PropertyValueComparer, false); } @@ -276,7 +324,7 @@ namespace Umbraco.Core.Models var (pvalue, change) = GetPValue(culture, segment, true); var origValue = pvalue.EditedValue; - var setValue = PropertyType.ConvertAssignedValue(value); + var setValue = ConvertAssignedValue(value); pvalue.EditedValue = setValue; @@ -284,7 +332,7 @@ namespace Umbraco.Core.Models } // bypasses all changes detection and is the *only* way to set the published value - internal void FactorySetValue(string culture, string segment, bool published, object value) + private void FactorySetValue(string culture, string segment, bool published, object value) { var (pvalue, _) = GetPValue(culture, segment, true); @@ -332,6 +380,128 @@ namespace Umbraco.Core.Models return (pvalue, change); } + /// + public object ConvertAssignedValue(object value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null; + + /// + /// Tries to convert a value assigned to a property. + /// + /// + /// + /// + private bool TryConvertAssignedValue(object value, bool throwOnError, out object converted) + { + var isOfExpectedType = IsOfExpectedPropertyType(value); + if (isOfExpectedType) + { + converted = value; + return true; + } + + // isOfExpectedType is true if value is null - so if false, value is *not* null + // "garbage-in", accept what we can & convert + // throw only if conversion is not possible + + var s = value.ToString(); + converted = null; + + switch (ValueStorageType) + { + case ValueStorageType.Nvarchar: + case ValueStorageType.Ntext: + { + converted = s; + return true; + } + + case ValueStorageType.Integer: + if (s.IsNullOrWhiteSpace()) + return true; // assume empty means null + var convInt = value.TryConvertTo(); + if (convInt) + { + converted = convInt.Result; + return true; + } + + if (throwOnError) + ThrowTypeException(value, typeof(int), Alias); + return false; + + case ValueStorageType.Decimal: + if (s.IsNullOrWhiteSpace()) + return true; // assume empty means null + var convDecimal = value.TryConvertTo(); + if (convDecimal) + { + // need to normalize the value (change the scaling factor and remove trailing zeros) + // because the underlying database is going to mess with the scaling factor anyways. + converted = convDecimal.Result.Normalize(); + return true; + } + + if (throwOnError) + ThrowTypeException(value, typeof(decimal), Alias); + return false; + + case ValueStorageType.Date: + if (s.IsNullOrWhiteSpace()) + return true; // assume empty means null + var convDateTime = value.TryConvertTo(); + if (convDateTime) + { + converted = convDateTime.Result; + return true; + } + + if (throwOnError) + ThrowTypeException(value, typeof(DateTime), Alias); + return false; + + default: + throw new NotSupportedException($"Not supported storage type \"{ValueStorageType}\"."); + } + } + + private static void ThrowTypeException(object value, Type expected, string alias) + { + throw new InvalidOperationException($"Cannot assign value \"{value}\" of type \"{value.GetType()}\" to property \"{alias}\" expecting type \"{expected}\"."); + } + + /// + /// Determines whether a value is of the expected type for this property type. + /// + /// + /// If the value is of the expected type, it can be directly assigned to the property. + /// Otherwise, some conversion is required. + /// + private bool IsOfExpectedPropertyType(object value) + { + // null values are assumed to be ok + if (value == null) + return true; + + // check if the type of the value matches the type from the DataType/PropertyEditor + // then it can be directly assigned, anything else requires conversion + var valueType = value.GetType(); + switch (ValueStorageType) + { + case ValueStorageType.Integer: + return valueType == typeof(int); + case ValueStorageType.Decimal: + return valueType == typeof(decimal); + case ValueStorageType.Date: + return valueType == typeof(DateTime); + case ValueStorageType.Nvarchar: + return valueType == typeof(string); + case ValueStorageType.Ntext: + return valueType == typeof(string); + default: + throw new NotSupportedException($"Not supported storage type \"{ValueStorageType}\"."); + } + } + + protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/PropertyCollection.cs b/src/Umbraco.Core/Models/PropertyCollection.cs index b82fd71eaf..2800b92d75 100644 --- a/src/Umbraco.Core/Models/PropertyCollection.cs +++ b/src/Umbraco.Core/Models/PropertyCollection.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Models /// /// Initializes a new instance of the class. /// - public PropertyCollection(IEnumerable properties) + public PropertyCollection(IEnumerable properties) : this() { Reset(properties); @@ -35,7 +35,7 @@ namespace Umbraco.Core.Models /// /// Replaces all properties, whilst maintaining validation delegates. /// - private void Reset(IEnumerable properties) + private void Reset(IEnumerable properties) { //collection events will be raised in each of these calls Clear(); diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 3cbe1ab70b..65c0ffeade 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -99,7 +99,7 @@ namespace Umbraco.Core.Models /// When false, getting the property value always return the edited value, /// regardless of the 'published' method parameter. /// - public bool SupportsPublishing { get; internal set; } + public bool SupportsPublishing { get; set; } /// [DataMember] @@ -210,136 +210,6 @@ namespace Umbraco.Core.Models return Variations.ValidateVariation(culture, segment, true, wildcards, false); } - /// - /// Creates a new property of this property type. - /// - public Property CreateProperty() - { - return new Property(this); - } - - /// - /// Determines whether a value is of the expected type for this property type. - /// - /// - /// If the value is of the expected type, it can be directly assigned to the property. - /// Otherwise, some conversion is required. - /// - private bool IsOfExpectedPropertyType(object value) - { - // null values are assumed to be ok - if (value == null) - return true; - - // check if the type of the value matches the type from the DataType/PropertyEditor - // then it can be directly assigned, anything else requires conversion - var valueType = value.GetType(); - switch (ValueStorageType) - { - case ValueStorageType.Integer: - return valueType == typeof(int); - case ValueStorageType.Decimal: - return valueType == typeof(decimal); - case ValueStorageType.Date: - return valueType == typeof(DateTime); - case ValueStorageType.Nvarchar: - return valueType == typeof(string); - case ValueStorageType.Ntext: - return valueType == typeof(string); - default: - throw new NotSupportedException($"Not supported storage type \"{ValueStorageType}\"."); - } - } - - /// - public object ConvertAssignedValue(object value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null; - - /// - /// Tries to convert a value assigned to a property. - /// - /// - /// - /// - private bool TryConvertAssignedValue(object value, bool throwOnError, out object converted) - { - var isOfExpectedType = IsOfExpectedPropertyType(value); - if (isOfExpectedType) - { - converted = value; - return true; - } - - // isOfExpectedType is true if value is null - so if false, value is *not* null - // "garbage-in", accept what we can & convert - // throw only if conversion is not possible - - var s = value.ToString(); - converted = null; - - switch (ValueStorageType) - { - case ValueStorageType.Nvarchar: - case ValueStorageType.Ntext: - { - converted = s; - return true; - } - - case ValueStorageType.Integer: - if (s.IsNullOrWhiteSpace()) - return true; // assume empty means null - var convInt = value.TryConvertTo(); - if (convInt) - { - converted = convInt.Result; - return true; - } - - if (throwOnError) - ThrowTypeException(value, typeof(int), Alias); - return false; - - case ValueStorageType.Decimal: - if (s.IsNullOrWhiteSpace()) - return true; // assume empty means null - var convDecimal = value.TryConvertTo(); - if (convDecimal) - { - // need to normalize the value (change the scaling factor and remove trailing zeros) - // because the underlying database is going to mess with the scaling factor anyways. - converted = convDecimal.Result.Normalize(); - return true; - } - - if (throwOnError) - ThrowTypeException(value, typeof(decimal), Alias); - return false; - - case ValueStorageType.Date: - if (s.IsNullOrWhiteSpace()) - return true; // assume empty means null - var convDateTime = value.TryConvertTo(); - if (convDateTime) - { - converted = convDateTime.Result; - return true; - } - - if (throwOnError) - ThrowTypeException(value, typeof(DateTime), Alias); - return false; - - default: - throw new NotSupportedException($"Not supported storage type \"{ValueStorageType}\"."); - } - } - - private static void ThrowTypeException(object value, Type expected, string alias) - { - throw new InvalidOperationException($"Cannot assign value \"{value}\" of type \"{value.GetType()}\" to property \"{alias}\" expecting type \"{expected}\"."); - } - - /// /// Sanitizes a property type alias. /// diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentTypeFactory.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentTypeFactory.cs index 89009ac7b8..ca78573999 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentTypeFactory.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentTypeFactory.cs @@ -18,7 +18,7 @@ /// The published content type owning the property. /// A property type. /// Is used by constructor to create property types. - IPublishedPropertyType CreatePropertyType(IPublishedContentType contentType, PropertyType propertyType); + IPublishedPropertyType CreatePropertyType(IPublishedContentType contentType, IPropertyType propertyType); /// /// Creates a published property type. diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs index 34094508c3..341d10b6b4 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs @@ -50,7 +50,7 @@ namespace Umbraco.Core.Models.PublishedContent } /// - public IPublishedPropertyType CreatePropertyType(IPublishedContentType contentType, PropertyType propertyType) + public IPublishedPropertyType CreatePropertyType(IPublishedContentType contentType, IPropertyType propertyType) { return new PublishedPropertyType(contentType, propertyType, _propertyValueConverters, _publishedModelFactory, this); } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index 0c2e62770e..b5e87ad6ff 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Models.PublishedContent /// /// The new published property type belongs to the published content type. /// - public PublishedPropertyType(IPublishedContentType contentType, PropertyType propertyType, PropertyValueConverterCollection propertyValueConverters, IPublishedModelFactory publishedModelFactory, IPublishedContentTypeFactory factory) + public PublishedPropertyType(IPublishedContentType contentType, IPropertyType propertyType, PropertyValueConverterCollection propertyValueConverters, IPublishedModelFactory publishedModelFactory, IPublishedContentTypeFactory factory) : this(propertyType.Alias, propertyType.DataTypeId, true, propertyType.Variations, propertyValueConverters, publishedModelFactory, factory) { ContentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); diff --git a/src/Umbraco.Core/Models/SimpleContentType.cs b/src/Umbraco.Core/Models/SimpleContentType.cs index fc84d15529..dde8450d90 100644 --- a/src/Umbraco.Core/Models/SimpleContentType.cs +++ b/src/Umbraco.Core/Models/SimpleContentType.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models { @@ -37,6 +35,7 @@ namespace Umbraco.Core.Models if (contentType == null) throw new ArgumentNullException(nameof(contentType)); Id = contentType.Id; + Key = contentType.Key; Alias = contentType.Alias; Variations = contentType.Variations; Icon = contentType.Icon; @@ -46,32 +45,26 @@ namespace Umbraco.Core.Models IsElement = contentType.IsElement; } - /// public string Alias { get; } public int Id { get; } - /// + public Guid Key { get; } + public ITemplate DefaultTemplate { get; } - /// public ContentVariation Variations { get; } - /// public string Icon { get; } - /// public bool IsContainer { get; } public string Name { get; } - /// public bool AllowedAsRoot { get; } - /// public bool IsElement { get; } - /// public bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false) { // non-exact validation: can accept a 'null' culture if the property type varies @@ -85,7 +78,6 @@ namespace Umbraco.Core.Models return string.Equals(Alias, other.Alias) && Id == other.Id; } - /// public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; @@ -94,7 +86,6 @@ namespace Umbraco.Core.Models return Equals((SimpleContentType) obj); } - /// public override int GetHashCode() { unchecked @@ -102,36 +93,5 @@ namespace Umbraco.Core.Models return ((Alias != null ? Alias.GetHashCode() : 0) * 397) ^ Id; } } - - // we have to have all this, because we're an IUmbracoEntity, because that is - // required by the query expression visitor / SimpleContentTypeMapper - // TODO: Make the query expression visitor use a different common interface, or investigate removing IRememberBeingDirty from being a requirement on that interface and expliclty checking for that throughout the code? - - string ITreeEntity.Name { get => this.Name; set => throw new NotImplementedException(); } - int IEntity.Id { get => this.Id; set => throw new NotImplementedException(); } - bool IEntity.HasIdentity => this.Id != default; - int ITreeEntity.CreatorId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - int ITreeEntity.ParentId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - int ITreeEntity.Level { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - string ITreeEntity.Path { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - int ITreeEntity.SortOrder { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - bool ITreeEntity.Trashed => throw new NotImplementedException(); - Guid IEntity.Key { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - DateTime IEntity.CreateDate { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - DateTime IEntity.UpdateDate { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - DateTime? IEntity.DeleteDate { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - void ITreeEntity.SetParent(ITreeEntity parent) => throw new NotImplementedException(); - object IDeepCloneable.DeepClone() => throw new NotImplementedException(); - bool IRememberBeingDirty.WasDirty() => throw new NotImplementedException(); - bool IRememberBeingDirty.WasPropertyDirty(string propertyName) => throw new NotImplementedException(); - void IRememberBeingDirty.ResetWereDirtyProperties() => throw new NotImplementedException(); - void IRememberBeingDirty.ResetDirtyProperties(bool rememberDirty) => throw new NotImplementedException(); - IEnumerable IRememberBeingDirty.GetWereDirtyProperties() => throw new NotImplementedException(); - bool ICanBeDirty.IsDirty() => throw new NotImplementedException(); - bool ICanBeDirty.IsPropertyDirty(string propName) => throw new NotImplementedException(); - IEnumerable ICanBeDirty.GetDirtyProperties() => throw new NotImplementedException(); - void ICanBeDirty.ResetDirtyProperties() => throw new NotImplementedException(); - public void DisableChangeTracking() => throw new NotImplementedException(); - public void EnableChangeTracking() => throw new NotImplementedException(); } } diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 4de7f32737..26f68c6262 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -552,6 +552,7 @@ namespace Umbraco.Core.Packaging private static XElement GetPackageInfoXml(PackageDefinition definition) { + var info = new XElement("info"); //Package info @@ -568,9 +569,9 @@ namespace Umbraco.Core.Packaging var requirements = new XElement("requirements"); - requirements.Add(new XElement("major", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Major.ToInvariantString() : definition.UmbracoVersion.Major.ToInvariantString())); - requirements.Add(new XElement("minor", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Minor.ToInvariantString() : definition.UmbracoVersion.Minor.ToInvariantString())); - requirements.Add(new XElement("patch", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Patch.ToInvariantString() : definition.UmbracoVersion.Build.ToInvariantString())); + requirements.Add(new XElement("major", definition.UmbracoVersion == null ? Current.UmbracoVersion.SemanticVersion.Major.ToInvariantString() : definition.UmbracoVersion.Major.ToInvariantString())); + requirements.Add(new XElement("minor", definition.UmbracoVersion == null ? Current.UmbracoVersion.SemanticVersion.Minor.ToInvariantString() : definition.UmbracoVersion.Minor.ToInvariantString())); + requirements.Add(new XElement("patch", definition.UmbracoVersion == null ? Current.UmbracoVersion.SemanticVersion.Patch.ToInvariantString() : definition.UmbracoVersion.Build.ToInvariantString())); if (definition.UmbracoVersion != null) requirements.Add(new XAttribute("type", RequirementsType.Strict.ToString())); diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs index fc31f61763..f844d14022 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs @@ -9,38 +9,28 @@ namespace Umbraco.Core.Persistence.Factories { internal static class PropertyFactory { - public static IEnumerable BuildEntities(PropertyType[] propertyTypes, IReadOnlyCollection dtos, int publishedVersionId, ILanguageRepository languageRepository) + public static IEnumerable BuildEntities(IPropertyType[] propertyTypes, IReadOnlyCollection dtos, int publishedVersionId, ILanguageRepository languageRepository) { - var properties = new List(); + var properties = new List(); var xdtos = dtos.GroupBy(x => x.PropertyTypeId).ToDictionary(x => x.Key, x => (IEnumerable)x); foreach (var propertyType in propertyTypes) { - var property = propertyType.CreateProperty(); + var values = new List(); + int propertyId = default; - try + // see notes in BuildDtos - we always have edit+published dtos + if (xdtos.TryGetValue(propertyType.Id, out var propDtos)) { - property.DisableChangeTracking(); - - // see notes in BuildDtos - we always have edit+published dtos - - if (xdtos.TryGetValue(propertyType.Id, out var propDtos)) + foreach (var propDto in propDtos) { - foreach (var propDto in propDtos) - { - property.Id = propDto.Id; - property.FactorySetValue(languageRepository.GetIsoCodeById(propDto.LanguageId), propDto.Segment, propDto.VersionId == publishedVersionId, propDto.Value); - } - + propertyId = propDto.Id; + values.Add(new Property.InitialPropertyValue(languageRepository.GetIsoCodeById(propDto.LanguageId), propDto.Segment, propDto.VersionId == publishedVersionId, propDto.Value)); } + } - property.ResetDirtyProperties(false); - properties.Add(property); - } - finally - { - property.EnableChangeTracking(); - } + var property = Property.CreateWithValues(propertyId, propertyType, values.ToArray()); + properties.Add(property); } return properties; diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs index db8e2b20d9..a3014000b6 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Persistence.Factories { internal static class PropertyGroupFactory { - + #region Implementation of IEntityFactory,IEnumerable> public static IEnumerable BuildEntity(IEnumerable groupDtos, @@ -115,7 +115,7 @@ namespace Umbraco.Core.Persistence.Factories return dto; } - internal static PropertyTypeDto BuildPropertyTypeDto(int tabId, PropertyType propertyType, int contentTypeId) + internal static PropertyTypeDto BuildPropertyTypeDto(int tabId, IPropertyType propertyType, int contentTypeId) { var propertyTypeDto = new PropertyTypeDto { diff --git a/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs b/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs index bfdd60e897..a569fa4912 100644 --- a/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/BaseMapper.cs @@ -52,6 +52,7 @@ namespace Umbraco.Core.Persistence.Mappers return mappedName; } + // fixme: TSource is used for nothing protected void DefineMap(string sourceName, string targetName) { if (_sqlSyntax == null) diff --git a/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs b/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs index dfa6a7ca5b..62d35c3eb8 100644 --- a/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs +++ b/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs @@ -5,6 +5,7 @@ namespace Umbraco.Core.Persistence.Mappers { public interface IMapperCollection : IBuilderCollection { + bool TryGetMapper(Type type, out BaseMapper mapper); BaseMapper this[Type type] { get; } } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MapperCollection.cs b/src/Umbraco.Core/Persistence/Mappers/MapperCollection.cs index 343406378a..20929dd188 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MapperCollection.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MapperCollection.cs @@ -10,27 +10,40 @@ namespace Umbraco.Core.Persistence.Mappers { public MapperCollection(IEnumerable items) : base(items) - { } + { - // maintain our own index for faster lookup - private readonly ConcurrentDictionary _index = new ConcurrentDictionary(); + _index = new Lazy>(() => + { + var d = new ConcurrentDictionary(); + foreach(var mapper in this) + { + var attributes = mapper.GetType().GetCustomAttributes(false); + foreach(var a in attributes) + { + d.TryAdd(a.EntityType, mapper); + } + } + return d; + }); + } + private readonly Lazy> _index; + + /// + /// Returns a mapper for this type, throw an exception if not found + /// + /// + /// public BaseMapper this[Type type] { get { - return _index.GetOrAdd(type, t => - { - // check if any of the mappers are assigned to this type - var mapper = this.FirstOrDefault(x => x.GetType() - .GetCustomAttributes(false) - .Any(m => m.EntityType == type)); - - if (mapper != null) return mapper; - - throw new Exception($"Could not find a mapper matching type {type.FullName}."); - }); + if (_index.Value.TryGetValue(type, out var mapper)) + return mapper; + throw new Exception($"Could not find a mapper matching type {type.FullName}."); } } + + public bool TryGetMapper(Type type, out BaseMapper mapper) => _index.Value.TryGetValue(type, out mapper); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/PropertyTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/PropertyTypeMapper.cs index ab1869a7f5..a9cabf1852 100644 --- a/src/Umbraco.Core/Persistence/Mappers/PropertyTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/PropertyTypeMapper.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Persistence.Dtos; namespace Umbraco.Core.Persistence.Mappers { /// - /// Represents a to DTO mapper used to translate the properties of the public api + /// Represents a to DTO mapper used to translate the properties of the public api /// implementation to that of the database's DTO as sql: [tableName].[columnName]. /// [MapperFor(typeof(PropertyType))] diff --git a/src/Umbraco.Core/Persistence/Mappers/SimpleContentTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/SimpleContentTypeMapper.cs index f98ff3b694..68df1550e5 100644 --- a/src/Umbraco.Core/Persistence/Mappers/SimpleContentTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/SimpleContentTypeMapper.cs @@ -5,6 +5,13 @@ using Umbraco.Core.Persistence.Dtos; namespace Umbraco.Core.Persistence.Mappers { + // TODO: This mapper is actually very useless because the only time it would ever be used is when trying to generate a strongly typed query + // on an IContentBase object which is what exposes ISimpleContentType, however the queries that we execute in the content repositories don't actually + // join on the content type table. The content type data is resolved outside of the query so the end result of the query that is generated by using + // this mapper will either fail or the syntax will target umbracoNode which will be filtering on the actual content NOT the content type. + // I'm leaving this here purely because the ExpressionTests rely on this which is fine for testing that the expressions work, but note that this + // resulting query will not. + [MapperFor(typeof(ISimpleContentType))] [MapperFor(typeof(SimpleContentType))] public sealed class SimpleContentTypeMapper : BaseMapper @@ -15,23 +22,16 @@ namespace Umbraco.Core.Persistence.Mappers protected override void DefineMaps() { + // There is no reason for using ContentType here instead of SimpleContentType, in fact the underlying DefineMap call does nothing with the first type parameter + DefineMap(nameof(ContentType.Id), nameof(NodeDto.NodeId)); - DefineMap(nameof(ContentType.CreateDate), nameof(NodeDto.CreateDate)); - DefineMap(nameof(ContentType.Level), nameof(NodeDto.Level)); - DefineMap(nameof(ContentType.ParentId), nameof(NodeDto.ParentId)); - DefineMap(nameof(ContentType.Path), nameof(NodeDto.Path)); - DefineMap(nameof(ContentType.SortOrder), nameof(NodeDto.SortOrder)); - DefineMap(nameof(ContentType.Name), nameof(NodeDto.Text)); - DefineMap(nameof(ContentType.Trashed), nameof(NodeDto.Trashed)); DefineMap(nameof(ContentType.Key), nameof(NodeDto.UniqueId)); - DefineMap(nameof(ContentType.CreatorId), nameof(NodeDto.UserId)); + DefineMap(nameof(ContentType.Name), nameof(NodeDto.Text)); DefineMap(nameof(ContentType.Alias), nameof(ContentTypeDto.Alias)); - DefineMap(nameof(ContentType.AllowedAsRoot), nameof(ContentTypeDto.AllowAtRoot)); - DefineMap(nameof(ContentType.Description), nameof(ContentTypeDto.Description)); DefineMap(nameof(ContentType.Icon), nameof(ContentTypeDto.Icon)); DefineMap(nameof(ContentType.IsContainer), nameof(ContentTypeDto.IsContainer)); + DefineMap(nameof(ContentType.AllowedAsRoot), nameof(ContentTypeDto.AllowAtRoot)); DefineMap(nameof(ContentType.IsElement), nameof(ContentTypeDto.IsElement)); - DefineMap(nameof(ContentType.Thumbnail), nameof(ContentTypeDto.Thumbnail)); } } } diff --git a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionVisitor.cs b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionVisitor.cs index c87937e41e..7ff536caba 100644 --- a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionVisitor.cs +++ b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionVisitor.cs @@ -60,8 +60,8 @@ namespace Umbraco.Core.Persistence.Querying if (m.Expression != null && m.Expression.Type != typeof(T) - && TypeHelper.IsTypeAssignableFrom(m.Expression.Type) //TODO: Could this just be `IEntity` ? why does it need to be IUmbracoEntity, we aren't even using the reference to that below - && EndsWithConstant(m) == false) + && EndsWithConstant(m) == false + && _mappers.TryGetMapper(m.Expression.Type, out var subMapper)) { //if this is the case, it means we have a sub expression / nested property access, such as: x.ContentType.Alias == "Test"; //and since the sub type (x.ContentType) is not the same as x, we need to resolve a mapper for x.ContentType to get it's mapped SQL column @@ -69,7 +69,6 @@ namespace Umbraco.Core.Persistence.Querying //don't execute if compiled if (Visited == false) { - var subMapper = _mappers[m.Expression.Type]; // throws if not found var field = subMapper.Map(m.Member.Name); if (field.IsNullOrWhiteSpace()) throw new InvalidOperationException($"The mapper returned an empty field for the member name: {m.Member.Name} for type: {m.Expression.Type}"); diff --git a/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs index d0fec639fe..203db8df93 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Persistence.Repositories public interface IContentTypeRepository : IContentTypeRepositoryBase { /// - /// Gets all entities of the specified query + /// Gets all entities of the specified query /// /// /// An enumerable list of objects diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs index 5e7c7a9b85..5803bc7b1d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -524,7 +524,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where T : class, IContentBase { var result = new Dictionary(); - var compositionPropertiesIndex = new Dictionary(); + var compositionPropertiesIndex = new Dictionary(); // index PropertyDataDto per versionId for perfs // merge edited and published dtos diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index c22d1f1200..7ec052a14c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -405,7 +405,7 @@ AND umbracoNode.id <> @id", } // collect property types that have a dirty variation - List propertyTypeVariationDirty = null; + List propertyTypeVariationDirty = null; // note: this only deals with *local* property types, we're dealing w/compositions later below foreach (var propertyType in entity.PropertyTypes) @@ -415,7 +415,7 @@ AND umbracoNode.id <> @id", { // allocate the list only when needed if (propertyTypeVariationDirty == null) - propertyTypeVariationDirty = new List(); + propertyTypeVariationDirty = new List(); propertyTypeVariationDirty.Add(propertyType); } @@ -571,7 +571,7 @@ AND umbracoNode.id <> @id", // gets property types that have actually changed, and the corresponding changes // returns null if no property type has actually changed - private Dictionary GetPropertyVariationChanges(IEnumerable propertyTypes) + private Dictionary GetPropertyVariationChanges(IEnumerable propertyTypes) { var propertyTypesL = propertyTypes.ToList(); @@ -1190,7 +1190,7 @@ AND umbracoNode.id <> @id", new { Id = contentTypeId, PropertyTypeId = propertyTypeId }); } - protected void ValidateAlias(PropertyType pt) + protected void ValidateAlias(IPropertyType pt) { if (string.IsNullOrWhiteSpace(pt.Alias)) { @@ -1221,7 +1221,7 @@ AND umbracoNode.id <> @id", /// Try to set the data type id based on its ControlId /// /// - private void AssignDataTypeFromPropertyEditor(PropertyType propertyType) + private void AssignDataTypeFromPropertyEditor(IPropertyType propertyType) { //we cannot try to assign a data type of it's empty if (propertyType.PropertyEditorAlias.IsNullOrWhiteSpace() == false) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs index 741c5922ea..a204ab53d4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -225,8 +225,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (builtinProperties.ContainsKey(propertyType.Alias)) { //this reset's its current data type reference which will be re-assigned based on the property editor assigned on the next line - var propDefinition = builtinProperties[propertyType.Alias]; - if (propDefinition != null) + if (builtinProperties.TryGetValue(propertyType.Alias, out var propDefinition) && propDefinition != null) { propertyType.DataTypeId = propDefinition.DataTypeId; propertyType.DataTypeKey = propDefinition.DataTypeKey; diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index 13422f43b1..6a1a3ee3f1 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -1,9 +1,10 @@ using System; -using System.Configuration; using System.Data.Common; using System.Threading; using NPoco; using NPoco.FluentMappings; +using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.FaultHandling; @@ -51,15 +52,15 @@ namespace Umbraco.Core.Persistence /// Initializes a new instance of the . /// /// Used by core runtime. - public UmbracoDatabaseFactory(ILogger logger, Lazy mappers) - : this(Constants.System.UmbracoConnectionName, logger, mappers) + public UmbracoDatabaseFactory(ILogger logger, Lazy mappers, Configs configs) + : this(Constants.System.UmbracoConnectionName, logger, mappers, configs) { } /// /// Initializes a new instance of the . /// /// Used by the other ctor and in tests. - public UmbracoDatabaseFactory(string connectionStringName, ILogger logger, Lazy mappers) + public UmbracoDatabaseFactory(string connectionStringName, ILogger logger, Lazy mappers, Configs configs) { if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentNullOrEmptyException(nameof(connectionStringName)); @@ -67,7 +68,8 @@ namespace Umbraco.Core.Persistence _mappers = mappers ?? throw new ArgumentNullException(nameof(mappers)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - var settings = ConfigurationManager.ConnectionStrings[connectionStringName]; + var settings = configs.ConnectionStrings()[connectionStringName]; + if (settings == null) { logger.Debug("Missing connection string, defer configuration."); @@ -135,7 +137,7 @@ namespace Umbraco.Core.Persistence { // replace NPoco database type by a more efficient one - var setting = ConfigurationManager.AppSettings[Constants.AppSettings.Debug.DatabaseFactoryServerVersion]; + var setting = Current.Configs.Global().DatabaseFactoryServerVersion; var fromSettings = false; if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.") diff --git a/src/Umbraco.Core/PropertyEditors/ParameterEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditorCollection.cs index 4dd4a75c22..dacda815ec 100644 --- a/src/Umbraco.Core/PropertyEditors/ParameterEditorCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditorCollection.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors { public class ParameterEditorCollection : BuilderCollectionBase { - public ParameterEditorCollection(DataEditorCollection dataEditors, ManifestParser manifestParser) + public ParameterEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser) : base(dataEditors .Where(x => (x.Type & EditorType.MacroParameter) > 0) .Union(manifestParser.Manifest.PropertyEditors)) @@ -15,11 +15,11 @@ namespace Umbraco.Core.PropertyEditors // note: virtual so it can be mocked public virtual IDataEditor this[string alias] => this.SingleOrDefault(x => x.Alias == alias); - + public virtual bool TryGet(string alias, out IDataEditor editor) { editor = this.FirstOrDefault(x => x.Alias == alias); return editor != null; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs index 712a66e55d..86cfde2ee4 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors { public class PropertyEditorCollection : BuilderCollectionBase { - public PropertyEditorCollection(DataEditorCollection dataEditors, ManifestParser manifestParser) + public PropertyEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser) : base(dataEditors .Where(x => (x.Type & EditorType.PropertyValue) > 0) .Union(manifestParser.Manifest.PropertyEditors)) @@ -20,11 +20,11 @@ namespace Umbraco.Core.PropertyEditors // note: virtual so it can be mocked public virtual IDataEditor this[string alias] => this.SingleOrDefault(x => x.Alias == alias); - + public virtual bool TryGet(string alias, out IDataEditor editor) { editor = this.FirstOrDefault(x => x.Alias == alias); return editor != null; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Runtime/CoreInitialComposer.cs b/src/Umbraco.Core/Runtime/CoreInitialComposer.cs index bc521b0328..61a9f472fe 100644 --- a/src/Umbraco.Core/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Core/Runtime/CoreInitialComposer.cs @@ -1,5 +1,4 @@ using System; -using System.Configuration; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Composing.CompositionExtensions; @@ -58,7 +57,7 @@ namespace Umbraco.Core.Runtime composition.Register(); // register manifest parser, will be injected in collection builders where needed - composition.RegisterUnique(); + composition.RegisterUnique(); // register our predefined validators composition.ManifestValueValidators() @@ -81,10 +80,11 @@ namespace Umbraco.Core.Runtime // register a server registrar, by default it's the db registrar composition.RegisterUnique(f => { - // TODO: this is a hack, use proper configuration! - // also: we still register the full IServerMessenger because + var globalSettings = f.GetInstance(); + + // TODO: we still register the full IServerMessenger because // even on 1 single server we can have 2 concurrent app domains - var singleServer = "true".InvariantEquals(ConfigurationManager.AppSettings[Constants.AppSettings.DisableElectionForSingleServer]); + var singleServer = globalSettings.DisableElectionForSingleServer; return singleServer ? (IServerRegistrar) new SingleServerRegistrar(f.GetInstance()) : new DatabaseServerRegistrar( diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index efecb539cb..98d245c04e 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -10,7 +10,6 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; -using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Sync; @@ -28,10 +27,31 @@ namespace Umbraco.Core.Runtime private IFactory _factory; private RuntimeState _state; + + public CoreRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger) + { + IOHelper = ioHelper; + Configs = configs; + UmbracoVersion = umbracoVersion ; + + Logger = logger; + // runtime state + // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' + // as the second one captures the current value (null) and therefore fails + _state = new RuntimeState(Logger, + Configs.Settings(), Configs.Global(), + new Lazy(() => _factory.GetInstance()), + new Lazy(() => _factory.GetInstance()), + UmbracoVersion) + { + Level = RuntimeLevel.Boot + }; + } + /// /// Gets the logger. /// - protected ILogger Logger { get; private set; } + protected ILogger Logger { get; } /// /// Gets the profiler. @@ -51,7 +71,9 @@ namespace Umbraco.Core.Runtime /// /// Gets the /// - protected IIOHelper IOHelper { get; private set; } + protected IIOHelper IOHelper { get; } + protected Configs Configs { get; } + protected IUmbracoVersion UmbracoVersion { get; } /// public IRuntimeState State => _state; @@ -63,18 +85,11 @@ namespace Umbraco.Core.Runtime // ie the bare minimum required to boot // loggers - var logger = Logger = GetLogger(); - if (logger == null) - throw new InvalidOperationException($"The object returned from {nameof(GetLogger)} cannot be null"); var profiler = Profiler = GetProfiler(); if (profiler == null) throw new InvalidOperationException($"The object returned from {nameof(GetProfiler)} cannot be null"); - var profilingLogger = ProfilingLogger = new ProfilingLogger(logger, profiler); - - IOHelper = GetIOHelper(); - if (IOHelper == null) - throw new InvalidOperationException($"The object returned from {nameof(GetIOHelper)} cannot be null"); + var profilingLogger = ProfilingLogger = new ProfilingLogger(Logger, profiler); TypeFinder = GetTypeFinder(); if (TypeFinder == null) @@ -89,17 +104,18 @@ namespace Umbraco.Core.Runtime // are NOT disposed - which is not a big deal as long as they remain lightweight // objects. + var umbracoVersion = new UmbracoVersion(); using (var timer = profilingLogger.TraceDuration( - $"Booting Umbraco {UmbracoVersion.SemanticVersion.ToSemanticString()}.", + $"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.", "Booted.", "Boot failed.")) { - logger.Info("Booting site '{HostingSiteName}', app '{HostingApplicationID}', path '{HostingPhysicalPath}', server '{MachineName}'.", + Logger.Info("Booting site '{HostingSiteName}', app '{HostingApplicationID}', path '{HostingPhysicalPath}', server '{MachineName}'.", HostingEnvironment.SiteName, HostingEnvironment.ApplicationID, HostingEnvironment.ApplicationPhysicalPath, NetworkHelper.MachineName); - logger.Debug("Runtime: {Runtime}", GetType().FullName); + Logger.Debug("Runtime: {Runtime}", GetType().FullName); // application environment ConfigureUnhandledException(); @@ -132,29 +148,15 @@ namespace Umbraco.Core.Runtime // database factory var databaseFactory = GetDatabaseFactory(); - // configs - var configs = GetConfigs(); - // type finder/loader - var typeLoader = new TypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(configs.Global().LocalTempPath), ProfilingLogger); - - // runtime state - // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' - // as the second one captures the current value (null) and therefore fails - _state = new RuntimeState(Logger, - configs.Settings(), configs.Global(), - new Lazy(() => _factory.GetInstance()), - new Lazy(() => _factory.GetInstance())) - { - Level = RuntimeLevel.Boot - }; + var typeLoader = new TypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(Configs.Global().LocalTempPath(IOHelper)), ProfilingLogger); // main dom var mainDom = new MainDom(Logger); // create the composition - composition = new Composition(register, typeLoader, ProfilingLogger, _state, configs); - composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, mainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper); + composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs); + composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, mainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion); // run handlers RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); @@ -218,6 +220,11 @@ namespace Umbraco.Core.Runtime return _factory; } + private IUmbracoVersion GetUmbracoVersion(IGlobalSettings globalSettings) + { + return new UmbracoVersion(globalSettings); + } + protected virtual void ConfigureUnhandledException() { //take care of unhandled exceptions - there is nothing we can do to @@ -324,12 +331,6 @@ namespace Umbraco.Core.Runtime protected virtual IEnumerable GetComposerTypes(TypeLoader typeLoader) => typeLoader.GetTypes(); - /// - /// Gets a logger. - /// - protected virtual ILogger GetLogger() - => SerilogLogger.CreateWithDefaultConfiguration(); - /// /// Gets a profiler. /// @@ -343,12 +344,6 @@ namespace Umbraco.Core.Runtime protected virtual ITypeFinder GetTypeFinder() => new TypeFinder(Logger); - /// - /// Gets a - /// - /// - protected virtual IIOHelper GetIOHelper() - => Umbraco.Core.IO.IOHelper.Default; /// /// Gets the application caches. @@ -375,17 +370,8 @@ namespace Umbraco.Core.Runtime /// /// This is strictly internal, for tests only. protected internal virtual IUmbracoDatabaseFactory GetDatabaseFactory() - => new UmbracoDatabaseFactory(Logger, new Lazy(() => _factory.GetInstance())); + => new UmbracoDatabaseFactory(Logger, new Lazy(() => _factory.GetInstance()), Configs); - /// - /// Gets the configurations. - /// - protected virtual Configs GetConfigs() - { - var configs = new Configs(); - configs.AddCoreConfigs(); - return configs; - } #endregion } diff --git a/src/Umbraco.Core/RuntimeOptions.cs b/src/Umbraco.Core/RuntimeOptions.cs index c0bae23446..23abd474a4 100644 --- a/src/Umbraco.Core/RuntimeOptions.cs +++ b/src/Umbraco.Core/RuntimeOptions.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Configuration; -using System.Runtime.CompilerServices; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Logging; @@ -19,43 +17,6 @@ namespace Umbraco.Core { private static List> _onBoot; private static List> _onEssentials; - private static bool? _installMissingDatabase; - private static bool? _installEmptyDatabase; - - // reads a boolean appSetting - private static bool BoolSetting(string key, bool missing) => ConfigurationManager.AppSettings[key]?.InvariantEquals("true") ?? missing; - - /// - /// Gets a value indicating whether the runtime should enter Install level when the database is missing. - /// - /// - /// By default, when a database connection string is configured but it is not possible to - /// connect to the database, the runtime enters the BootFailed level. If this options is set to true, - /// it enters the Install level instead. - /// It is then up to the implementor, that is setting this value, to take over the installation - /// sequence. - /// - public static bool InstallMissingDatabase - { - get => _installEmptyDatabase ?? BoolSetting("Umbraco.Core.RuntimeState.InstallMissingDatabase", false); - set => _installEmptyDatabase = value; - } - - /// - /// Gets a value indicating whether the runtime should enter Install level when the database is empty. - /// - /// - /// By default, when a database connection string is configured and it is possible to connect to - /// the database, but the database is empty, the runtime enters the BootFailed level. If this options - /// is set to true, it enters the Install level instead. - /// It is then up to the implementor, that is setting this value, to take over the installation - /// sequence. - /// - public static bool InstallEmptyDatabase - { - get => _installMissingDatabase ?? BoolSetting("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false); - set => _installMissingDatabase = value; - } /// /// Executes the RuntimeBoot handlers. diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs index 5d34fe70a1..e0ce17f769 100644 --- a/src/Umbraco.Core/RuntimeState.cs +++ b/src/Umbraco.Core/RuntimeState.cs @@ -25,18 +25,20 @@ namespace Umbraco.Core private readonly HashSet _applicationUrls = new HashSet(); private readonly Lazy _mainDom; private readonly Lazy _serverRegistrar; + private readonly IUmbracoVersion _umbracoVersion; /// /// Initializes a new instance of the class. /// public RuntimeState(ILogger logger, IUmbracoSettingsSection settings, IGlobalSettings globalSettings, - Lazy mainDom, Lazy serverRegistrar) + Lazy mainDom, Lazy serverRegistrar, IUmbracoVersion umbracoVersion) { _logger = logger; _settings = settings; _globalSettings = globalSettings; _mainDom = mainDom; _serverRegistrar = serverRegistrar; + _umbracoVersion = umbracoVersion; } /// @@ -56,16 +58,16 @@ namespace Umbraco.Core public IMainDom MainDom => _mainDom.Value; /// - public Version Version => UmbracoVersion.Current; + public Version Version => _umbracoVersion.Current; /// - public string VersionComment => UmbracoVersion.Comment; + public string VersionComment => _umbracoVersion.Comment; /// - public SemVersion SemanticVersion => UmbracoVersion.SemanticVersion; + public SemVersion SemanticVersion => _umbracoVersion.SemanticVersion; /// - public bool Debug { get; } = GlobalSettings.DebugMode; + public bool Debug => HttpContext.Current != null ? HttpContext.Current.IsDebuggingEnabled : _globalSettings.DebugMode; /// public bool IsMainDom => MainDom.IsMainDom; @@ -125,7 +127,7 @@ namespace Umbraco.Core /// public void DetermineRuntimeLevel(IUmbracoDatabaseFactory databaseFactory, ILogger logger) { - var localVersion = UmbracoVersion.LocalVersion; // the local, files, version + var localVersion = _umbracoVersion.LocalVersion; // the local, files, version var codeVersion = SemanticVersion; // the executing code version var connect = false; @@ -167,7 +169,7 @@ namespace Umbraco.Core // else, keep going, // anything other than install wants a database - see if we can connect // (since this is an already existing database, assume localdb is ready) - var tries = RuntimeOptions.InstallMissingDatabase ? 2 : 5; + var tries = _globalSettings.InstallMissingDatabase ? 2 : 5; for (var i = 0;;) { connect = databaseFactory.CanConnect; @@ -181,7 +183,7 @@ namespace Umbraco.Core // cannot connect to configured database, this is bad, fail logger.Debug("Could not connect to database."); - if (RuntimeOptions.InstallMissingDatabase) + if (_globalSettings.InstallMissingDatabase) { // ok to install on a configured but missing database Level = RuntimeLevel.Install; @@ -210,7 +212,7 @@ namespace Umbraco.Core // can connect to the database but cannot check the upgrade state... oops logger.Warn(e, "Could not check the upgrade state."); - if (RuntimeOptions.InstallEmptyDatabase) + if (_globalSettings.InstallEmptyDatabase) { // ok to install on an empty database Level = RuntimeLevel.Install; diff --git a/src/Umbraco.Core/Security/MembershipProviderBase.cs b/src/Umbraco.Core/Security/MembershipProviderBase.cs index 633e12bcc1..aa0ef43b5c 100644 --- a/src/Umbraco.Core/Security/MembershipProviderBase.cs +++ b/src/Umbraco.Core/Security/MembershipProviderBase.cs @@ -10,9 +10,7 @@ using System.Web.Configuration; using System.Web.Hosting; using System.Web.Security; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; -using Umbraco.Core.Models; namespace Umbraco.Core.Security { diff --git a/src/Umbraco.Core/Services/IDataTypeService.cs b/src/Umbraco.Core/Services/IDataTypeService.cs index bedf6fdfad..b78607462c 100644 --- a/src/Umbraco.Core/Services/IDataTypeService.cs +++ b/src/Umbraco.Core/Services/IDataTypeService.cs @@ -82,7 +82,7 @@ namespace Umbraco.Core.Services /// /// /// Please note that deleting a will remove - /// all the data that references this . + /// all the data that references this . /// /// to delete /// Id of the user issuing the deletion diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index 705a876d83..ad10a1371b 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -148,16 +148,13 @@ namespace Umbraco.Core.Services.Implement // existing property alias change? var hasAnyPropertyChangedAlias = contentType.PropertyTypes.Any(propertyType => { - if (!(propertyType is IRememberBeingDirty dirtyProperty)) - throw new Exception("oops"); - // skip new properties // TODO: This used to be WasPropertyDirty("HasIdentity") but i don't think that actually worked for detecting new entities this does seem to work properly - var isNewProperty = dirtyProperty.WasPropertyDirty("Id"); + var isNewProperty = propertyType.WasPropertyDirty("Id"); if (isNewProperty) return false; // alias change? - return dirtyProperty.WasPropertyDirty("Alias"); + return propertyType.WasPropertyDirty("Alias"); }); // removed properties? diff --git a/src/Umbraco.Core/Services/Implement/DataTypeService.cs b/src/Umbraco.Core/Services/Implement/DataTypeService.cs index 5a93fb91b1..f9d0256568 100644 --- a/src/Umbraco.Core/Services/Implement/DataTypeService.cs +++ b/src/Umbraco.Core/Services/Implement/DataTypeService.cs @@ -414,7 +414,7 @@ namespace Umbraco.Core.Services.Implement /// /// /// Please note that deleting a will remove - /// all the data that references this . + /// all the data that references this . /// /// to delete /// Optional Id of the user issuing the deletion diff --git a/src/Umbraco.Core/Services/Implement/KeyValueService.cs b/src/Umbraco.Core/Services/Implement/KeyValueService.cs index b3f3f2468d..d5d8e66525 100644 --- a/src/Umbraco.Core/Services/Implement/KeyValueService.cs +++ b/src/Umbraco.Core/Services/Implement/KeyValueService.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Migrations; @@ -14,12 +15,14 @@ namespace Umbraco.Core.Services.Implement private readonly object _initialock = new object(); private readonly IScopeProvider _scopeProvider; private readonly ILogger _logger; + private readonly IUmbracoVersion _umbracoVersion; private bool _initialized; - public KeyValueService(IScopeProvider scopeProvider, ILogger logger) + public KeyValueService(IScopeProvider scopeProvider, ILogger logger, IUmbracoVersion umbracoVersion) { _scopeProvider = scopeProvider; _logger = logger; + _umbracoVersion = umbracoVersion; } private void EnsureInitialized() @@ -39,7 +42,7 @@ namespace Umbraco.Core.Services.Implement // if already running 8, either following an upgrade or an install, // then everything should be ok (the table should exist, etc) - if (UmbracoVersion.LocalVersion != null && UmbracoVersion.LocalVersion.Major >= 8) + if (_umbracoVersion.LocalVersion != null && _umbracoVersion.LocalVersion.Major >= 8) { _initialized = true; return; @@ -202,9 +205,7 @@ namespace Umbraco.Core.Services.Implement /// Used by to determine the runtime state. internal static string GetValue(IUmbracoDatabase database, string key) { - // not 8 yet = no key/value table, no value - if (UmbracoVersion.LocalVersion.Major < 8) - return null; + if (database is null) return null; var sql = database.SqlContext.Sql() .Select() diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs index 7442169b44..118080feb6 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs @@ -534,7 +534,7 @@ namespace Umbraco.Core.Sync { var fileName = HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty) + "-lastsynced.txt"; - var distCacheFilePath = Path.Combine(globalSettings.LocalTempPath, "DistCache", fileName); + var distCacheFilePath = Path.Combine(globalSettings.LocalTempPath(Current.IOHelper), "DistCache", fileName); //ensure the folder exists var folder = Path.GetDirectoryName(distCacheFilePath); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index eae73c28bc..b02a7df78c 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -136,17 +136,12 @@ - - - - - @@ -154,27 +149,16 @@ - - + - - - - - - - - - - @@ -184,6 +168,7 @@ + @@ -213,33 +198,26 @@ - - - - - - - - - + + + + - - - + @@ -260,9 +238,7 @@ - - @@ -274,59 +250,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -397,6 +322,7 @@ + @@ -418,7 +344,6 @@ - @@ -475,10 +400,7 @@ - - - @@ -495,13 +417,9 @@ - - - - @@ -520,7 +438,9 @@ + + @@ -531,12 +451,6 @@ - - - - - - @@ -589,9 +503,7 @@ - - @@ -976,7 +888,6 @@ - @@ -985,7 +896,6 @@ - @@ -1000,7 +910,6 @@ - @@ -1041,6 +950,5 @@ Umbraco.Abstractions - \ No newline at end of file diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs index 9fd1bf46dc..8aedd8f263 100644 --- a/src/Umbraco.Core/UriExtensions.cs +++ b/src/Umbraco.Core/UriExtensions.cs @@ -52,9 +52,10 @@ namespace Umbraco.Core //if not, then def not back office if (isUmbracoPath == false) return false; + var mvcArea = globalSettings.GetUmbracoMvcArea(Current.IOHelper); //if its the normal /umbraco path - if (urlPath.InvariantEquals("/" + globalSettings.GetUmbracoMvcArea()) - || urlPath.InvariantEquals("/" + globalSettings.GetUmbracoMvcArea() + "/")) + if (urlPath.InvariantEquals("/" + mvcArea) + || urlPath.InvariantEquals("/" + mvcArea + "/")) { return true; } @@ -75,15 +76,15 @@ namespace Umbraco.Core } //check for special back office paths - if (urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/BackOffice/") - || urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/Preview/")) + if (urlPath.InvariantStartsWith("/" + mvcArea + "/BackOffice/") + || urlPath.InvariantStartsWith("/" + mvcArea + "/Preview/")) { return true; } //check for special front-end paths - if (urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/Surface/") - || urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/Api/")) + if (urlPath.InvariantStartsWith("/" + mvcArea + "/Surface/") + || urlPath.InvariantStartsWith("/" + mvcArea + "/Api/")) { return false; } diff --git a/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs index d6dc1f8c73..dc260c4a3b 100644 --- a/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Benchmarks [GlobalSetup] public void Setup() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var path = TestHelper.CurrentAssemblyDirectory; SetupSqlCe(path, logger); diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 4ef08a15f5..ee78360716 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -24,9 +24,9 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var register = RegisterFactory.Create(); + var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.RegisterUnique(_ => new TestServerRegistrar()); composition.RegisterUnique(_ => new TestServerMessenger()); diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 232d74ba6a..89bcd48d05 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Compose; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -25,6 +26,7 @@ namespace Umbraco.Tests.Components private static readonly List Composed = new List(); private static readonly List Initialized = new List(); private static readonly List Terminated = new List(); + private static readonly Configs Configs = TestHelper.GetConfigs(); private static IFactory MockFactory(Action> setup = null) { @@ -34,7 +36,7 @@ namespace Umbraco.Tests.Components var logger = Mock.Of(); var typeFinder = new TypeFinder(logger); - var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty()))); + var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty())), TestHelper.GetConfigs()); var fs = new FileSystems(mock.Object, logger, IOHelper.Default, SettingsForTests.GenerateMockGlobalSettings()); var p = new ScopeProvider(f, fs, logger, typeFinder); @@ -69,7 +71,7 @@ namespace Umbraco.Tests.Components public void Boot1A() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = TypeArray(); var composers = new Composers(composition, types, Mock.Of()); @@ -108,7 +110,7 @@ namespace Umbraco.Tests.Components public void Boot1B() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); var types = TypeArray(); var composers = new Composers(composition, types, Mock.Of()); @@ -124,7 +126,7 @@ namespace Umbraco.Tests.Components public void Boot2() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = TypeArray(); var composers = new Composers(composition, types, Mock.Of()); @@ -139,7 +141,7 @@ namespace Umbraco.Tests.Components public void Boot3() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = TypeArray(); var composers = new Composers(composition, types, Mock.Of()); @@ -156,7 +158,7 @@ namespace Umbraco.Tests.Components public void BrokenRequire() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = TypeArray(); var composers = new Composers(composition, types, Mock.Of()); @@ -179,7 +181,7 @@ namespace Umbraco.Tests.Components public void BrokenRequired() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = TypeArray(); var composers = new Composers(composition, types, Mock.Of()); @@ -214,7 +216,7 @@ namespace Umbraco.Tests.Components throw new NotSupportedException(type.FullName); }); }); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = new[] { typeof(Composer1), typeof(Composer5), typeof(Composer5a) }; var composers = new Composers(composition, types, Mock.Of()); @@ -240,7 +242,7 @@ namespace Umbraco.Tests.Components public void Requires1() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs()); var types = new[] { typeof(Composer6), typeof(Composer7), typeof(Composer8) }; var composers = new Composers(composition, types, Mock.Of()); @@ -255,7 +257,7 @@ namespace Umbraco.Tests.Components public void Requires2A() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; var composers = new Composers(composition, types, Mock.Of()); @@ -272,7 +274,7 @@ namespace Umbraco.Tests.Components { var register = MockRegister(); var factory = MockFactory(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), Configs); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; var composers = new Composers(composition, types, Mock.Of()); @@ -291,7 +293,7 @@ namespace Umbraco.Tests.Components public void WeakDependencies() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs); var types = new[] { typeof(Composer10) }; var composers = new Composers(composition, types, Mock.Of()); @@ -330,7 +332,7 @@ namespace Umbraco.Tests.Components public void DisableMissing() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs); var types = new[] { typeof(Composer6), typeof(Composer8) }; // 8 disables 7 which is not in the list var composers = new Composers(composition, types, Mock.Of()); @@ -345,7 +347,7 @@ namespace Umbraco.Tests.Components public void AttributesPriorities() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown)); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs); var types = new[] { typeof(Composer26) }; // 26 disabled by assembly attribute var composers = new Composers(composition, types, Mock.Of()); @@ -370,7 +372,7 @@ namespace Umbraco.Tests.Components var typeLoader = new TypeLoader(ioHelper, typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of()); var register = MockRegister(); - var composition = new Composition(register, typeLoader, Mock.Of(), MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(register, typeLoader, Mock.Of(), MockRuntimeState(RuntimeLevel.Run), Configs); var types = typeLoader.GetTypes().Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web")); var composers = new Composers(composition, types, Mock.Of()); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 339bc7a3aa..53b4a9c380 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -5,6 +5,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Tests.Components; using Umbraco.Tests.TestHelpers; @@ -21,8 +22,8 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - var register = RegisterFactory.Create(); - _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var register = TestHelper.GetRegister(); + _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); } [TearDown] diff --git a/src/Umbraco.Tests/Composing/CompositionTests.cs b/src/Umbraco.Tests/Composing/CompositionTests.cs index 5516d6cab8..560f79fb24 100644 --- a/src/Umbraco.Tests/Composing/CompositionTests.cs +++ b/src/Umbraco.Tests/Composing/CompositionTests.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Composing { @@ -40,7 +41,7 @@ namespace Umbraco.Tests.Composing var typeFinder = new TypeFinder(Mock.Of()); var ioHelper = IOHelper.Default; var typeLoader = new TypeLoader(ioHelper, typeFinder, Mock.Of(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger); - var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of()); + var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of(), TestHelper.GetConfigs()); // create the factory, ensure it is the mocked factory var factory = composition.CreateFactory(); diff --git a/src/Umbraco.Tests/Composing/ContainerConformingTests.cs b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs index f5c1ff9bc7..4ec6dfc0d5 100644 --- a/src/Umbraco.Tests/Composing/ContainerConformingTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Composing { @@ -12,7 +13,7 @@ namespace Umbraco.Tests.Composing { // tests that a container conforms - private IRegister GetRegister() => RegisterFactory.Create(); + private IRegister GetRegister() => TestHelper.GetRegister(); [Test] public void CanRegisterAndGet() diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index ed5a6e3ee2..6ba6a4c9b0 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Composing private IRegister CreateRegister() { - return RegisterFactory.Create(); + return TestHelper.GetRegister(); } // note @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Add() @@ -67,7 +67,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -92,7 +92,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Add() @@ -118,7 +118,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Add() @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 5586f6baa0..d4709ae03a 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -19,9 +19,9 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = RegisterFactory.Create(); - - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var container = TestHelper.GetRegister(); + + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests/Composing/TypeFinderTests.cs index fd070dee2a..5fe4c241d6 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeFinderTests.cs @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Composing private static IProfilingLogger GetTestProfilingLogger() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var profiler = new TestProfiler(); return new ProfilingLogger(logger, profiler); } diff --git a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs index 2b5611deec..65027edc73 100644 --- a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs @@ -26,17 +26,11 @@ namespace Umbraco.Tests.Configurations Current.IOHelper.Root = _root; } - [Test] - public void Is_Debug_Mode() - { - Assert.That(GlobalSettings.DebugMode, Is.EqualTo(true)); - } - [Ignore("fixme - ignored test")] [Test] public void Is_Version_From_Assembly_Correct() { - Assert.That(UmbracoVersion.SemanticVersion, Is.EqualTo("6.0.0")); + Assert.That(Current.UmbracoVersion.SemanticVersion, Is.EqualTo("6.0.0")); } [TestCase("~/umbraco", "/", "umbraco")] @@ -52,7 +46,7 @@ namespace Umbraco.Tests.Configurations globalSettingsMock.Setup(x => x.Path).Returns(() => Current.IOHelper.ResolveUrl(path)); Current.IOHelper.Root = rootPath; - Assert.AreEqual(outcome, globalSettings.GetUmbracoMvcAreaNoCache()); + Assert.AreEqual(outcome, globalSettings.GetUmbracoMvcAreaNoCache(IOHelper)); } diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/web.config b/src/Umbraco.Tests/Configurations/UmbracoSettings/web.config index 3b247ecbff..5ac2d56d14 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/web.config +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/web.config @@ -1,10 +1,10 @@  - + -
-
+
+
@@ -13,4 +13,4 @@ - \ No newline at end of file + diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index c4e4428e1a..8030927233 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -26,9 +26,9 @@ namespace Umbraco.Tests.IO [SetUp] public void Setup() { - _register = RegisterFactory.Create(); + _register = TestHelper.GetRegister(); - var composition = new Composition(_register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(_register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index 0c57c70742..6bf7e808a9 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; @@ -26,7 +27,7 @@ namespace Umbraco.Tests.Macros //Current.ApplicationContext = new ApplicationContext(cacheHelper, new ProfilingLogger(Mock.Of(), Mock.Of())); Current.Reset(); - Current.UnlockConfigs(); + Current.UnlockConfigs(TestHelper.GetConfigsFactory()); Current.Configs.Add(SettingsForTests.GetDefaultUmbracoSettings); } diff --git a/src/Umbraco.Tests/Membership/UmbracoServiceMembershipProviderTests.cs b/src/Umbraco.Tests/Membership/UmbracoServiceMembershipProviderTests.cs index 1c91d8a920..c70f304d66 100644 --- a/src/Umbraco.Tests/Membership/UmbracoServiceMembershipProviderTests.cs +++ b/src/Umbraco.Tests/Membership/UmbracoServiceMembershipProviderTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.Membership { var memberTypeServiceMock = new Mock(); memberTypeServiceMock.Setup(x => x.GetDefault()).Returns("Blah"); - var provider = new MembersMembershipProvider(Mock.Of(), memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(Mock.Of(), memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection()); Assert.AreEqual("Blah", provider.DefaultMemberTypeAlias); @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Membership { var memberTypeServiceMock = new Mock(); memberTypeServiceMock.Setup(x => x.GetDefault()).Returns("Blah"); - var provider = new MembersMembershipProvider(Mock.Of(), memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(Mock.Of(), memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection { { "defaultMemberTypeAlias", "Hello" } }); Assert.AreEqual("Hello", provider.DefaultMemberTypeAlias); @@ -48,7 +48,7 @@ namespace Umbraco.Tests.Membership var membershipServiceMock = new Mock(); membershipServiceMock.Setup(service => service.Exists("test")).Returns(true); - var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection()); MembershipCreateStatus status; @@ -65,7 +65,7 @@ namespace Umbraco.Tests.Membership var membershipServiceMock = new Mock(); membershipServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => new Member("test", MockedContentTypes.CreateSimpleMemberType())); - var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection { { "requiresUniqueEmail", "true" } }); MembershipCreateStatus status; @@ -95,7 +95,7 @@ namespace Umbraco.Tests.Membership createdMember = new Member("test", e, u, p, memberType, isApproved); }) .Returns(() => createdMember); - var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection()); @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Membership }) .Returns(() => createdMember); - var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection { { "passwordFormat", "Encrypted" } }); @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Membership }) .Returns(() => createdMember); - var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object); + var provider = new MembersMembershipProvider(membershipServiceMock.Object, memberTypeServiceMock.Object, TestHelper.GetUmbracoVersion()); provider.Initialize("test", new NameValueCollection { { "passwordFormat", "Hashed" }, { "hashAlgorithmType", "HMACSHA256" } }); diff --git a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs index c13d141fa5..01c93a40ec 100644 --- a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Migrations [Test] public void CreateTableOfTDto() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var builder = Mock.Of(); Mock.Get(builder) @@ -53,7 +53,7 @@ namespace Umbraco.Tests.Migrations [Test] public void DeleteKeysAndIndexesOfTDto() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var builder = Mock.Of(); Mock.Get(builder) @@ -87,7 +87,7 @@ namespace Umbraco.Tests.Migrations [Test] public void CreateKeysAndIndexesOfTDto() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var builder = Mock.Of(); Mock.Get(builder) @@ -124,7 +124,7 @@ namespace Umbraco.Tests.Migrations [Test] public void CreateKeysAndIndexes() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var builder = Mock.Of(); Mock.Get(builder) @@ -161,7 +161,7 @@ namespace Umbraco.Tests.Migrations [Test] public void CreateColumn() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var builder = Mock.Of(); Mock.Get(builder) diff --git a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs index 79878a59a1..8283b0b65a 100644 --- a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs +++ b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Misc [Test] public void NoApplicationUrlByDefault() { - var state = new RuntimeState(Mock.Of(), Mock.Of(), Mock.Of(), new Lazy(), new Lazy()); + var state = new RuntimeState(Mock.Of(), Mock.Of(), Mock.Of(), new Lazy(), new Lazy(), TestHelper.GetUmbracoVersion()); Assert.IsNull(state.ApplicationUrl); } @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Misc var registrar = new Mock(); registrar.Setup(x => x.GetCurrentServerUmbracoApplicationUrl()).Returns("http://server1.com/umbraco"); - var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => registrar.Object)); + var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => registrar.Object), TestHelper.GetUmbracoVersion()); state.EnsureApplicationUrl(); @@ -67,7 +67,7 @@ namespace Umbraco.Tests.Misc - var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => Mock.Of())); + var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => Mock.Of()), TestHelper.GetUmbracoVersion()); state.EnsureApplicationUrl(); @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Misc // still NOT set Assert.IsNull(url); } - + [Test] public void SetApplicationUrlFromWrSettingsSsl() { diff --git a/src/Umbraco.Tests/Models/Collections/Item.cs b/src/Umbraco.Tests/Models/Collections/Item.cs index 7c7f207aa2..38cf8ecb4b 100644 --- a/src/Umbraco.Tests/Models/Collections/Item.cs +++ b/src/Umbraco.Tests/Models/Collections/Item.cs @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Models.Collections PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyInfo.Name)); } - internal virtual void ResetIdentity() + public virtual void ResetIdentity() { _hasIdentity = false; _id = default(int); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index ee6649dd2b..bdb1a193bc 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -238,7 +238,7 @@ namespace Umbraco.Tests.Models private static IProfilingLogger GetTestProfilingLogger() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var profiler = new TestProfiler(); return new ProfilingLogger(logger, profiler); } diff --git a/src/Umbraco.Tests/Models/ContentTypeTests.cs b/src/Umbraco.Tests/Models/ContentTypeTests.cs index 7d4b1cdcc7..afb9ea1bdf 100644 --- a/src/Umbraco.Tests/Models/ContentTypeTests.cs +++ b/src/Umbraco.Tests/Models/ContentTypeTests.cs @@ -130,7 +130,7 @@ namespace Umbraco.Tests.Models private static IProfilingLogger GetTestProfilingLogger() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var profiler = new TestProfiler(); return new ProfilingLogger(logger, profiler); } diff --git a/src/Umbraco.Tests/Models/MacroTests.cs b/src/Umbraco.Tests/Models/MacroTests.cs index d980cd1d58..e263d99cec 100644 --- a/src/Umbraco.Tests/Models/MacroTests.cs +++ b/src/Umbraco.Tests/Models/MacroTests.cs @@ -2,6 +2,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Tests.TestHelpers; @@ -15,7 +16,7 @@ namespace Umbraco.Tests.Models public void Init() { Current.Reset(); - Current.UnlockConfigs(); + Current.UnlockConfigs(TestHelper.GetConfigsFactory()); Current.Configs.Add(SettingsForTests.GetDefaultUmbracoSettings); } diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 968e51ab97..7274ebcc98 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -626,7 +626,7 @@ namespace Umbraco.Tests.Models.Mapping } }; - var result = Mapper.Map(basic); + var result = Mapper.Map(basic); Assert.AreEqual(basic.Id, result.Id); Assert.AreEqual(basic.SortOrder, result.SortOrder); @@ -660,7 +660,7 @@ namespace Umbraco.Tests.Models.Mapping } }; - var result = Mapper.Map(basic); + var result = Mapper.Map(basic); Assert.AreEqual(basic.Id, result.Id); Assert.AreEqual(basic.SortOrder, result.SortOrder); diff --git a/src/Umbraco.Tests/Models/MemberTests.cs b/src/Umbraco.Tests/Models/MemberTests.cs index 4680ee67f5..836ce54afa 100644 --- a/src/Umbraco.Tests/Models/MemberTests.cs +++ b/src/Umbraco.Tests/Models/MemberTests.cs @@ -4,6 +4,7 @@ using System.Linq; using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Serialization; using Umbraco.Tests.TestHelpers; @@ -18,7 +19,7 @@ namespace Umbraco.Tests.Models public void Setup() { Current.Reset(); - Current.UnlockConfigs(); + Current.UnlockConfigs(TestHelper.GetConfigsFactory()); Current.Configs.Add(SettingsForTests.GetDefaultGlobalSettings); Current.Configs.Add(SettingsForTests.GetDefaultUmbracoSettings); } diff --git a/src/Umbraco.Tests/Models/UserTests.cs b/src/Umbraco.Tests/Models/UserTests.cs index 705301b9ed..603cd84a1a 100644 --- a/src/Umbraco.Tests/Models/UserTests.cs +++ b/src/Umbraco.Tests/Models/UserTests.cs @@ -4,6 +4,7 @@ using System.Linq; using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Models.Membership; using Umbraco.Core.Serialization; using Umbraco.Tests.TestHelpers; @@ -17,7 +18,7 @@ namespace Umbraco.Tests.Models public void Setup() { Current.Reset(); - Current.UnlockConfigs(); + Current.UnlockConfigs(TestHelper.GetConfigsFactory()); Current.Configs.Add(SettingsForTests.GetDefaultGlobalSettings); } diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index c7ebb9ef71..c2651a6ff6 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models Current.Reset(); - var configs = new Configs(); + var configs = TestHelper.GetConfigs(); configs.Add(SettingsForTests.GetDefaultGlobalSettings); configs.Add(SettingsForTests.GetDefaultUmbracoSettings); diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index fb451b1d5c..7ab9d2e28a 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Persistence _sqlCeSyntaxProvider = new SqlCeSyntaxProvider(); _sqlSyntaxProviders = new[] { (ISqlSyntaxProvider) _sqlCeSyntaxProvider }; _logger = Mock.Of(); - _databaseFactory = new UmbracoDatabaseFactory(_logger, new Lazy(() => Mock.Of())); + _databaseFactory = new UmbracoDatabaseFactory(_logger, new Lazy(() => Mock.Of()), TestHelper.GetConfigs()); } [TearDown] diff --git a/src/Umbraco.Tests/Persistence/NPocoTests/NPocoBulkInsertTests.cs b/src/Umbraco.Tests/Persistence/NPocoTests/NPocoBulkInsertTests.cs index 2a6c1f4e12..85b07d4828 100644 --- a/src/Umbraco.Tests/Persistence/NPocoTests/NPocoBulkInsertTests.cs +++ b/src/Umbraco.Tests/Persistence/NPocoTests/NPocoBulkInsertTests.cs @@ -92,7 +92,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests // create the db // prob not what we want, this is not a real database, but hey, the test is ignored anyways // we'll fix this when we have proper testing infrastructure - var dbSqlServer = TestObjects.GetUmbracoSqlServerDatabase(new DebugDiagnosticsLogger()); + var dbSqlServer = TestObjects.GetUmbracoSqlServerDatabase(new DebugDiagnosticsLogger(new MessageTemplates())); //drop the table dbSqlServer.Execute("DROP TABLE [umbracoServer]"); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 787853e4cb..997b275655 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.SetUp(); _fileSystems = Mock.Of(); - _fileSystem = new PhysicalFileSystem(new GlobalSettings(IOHelper).UmbracoScriptsPath, IOHelper); + _fileSystem = new PhysicalFileSystem(SettingsForTests.GenerateMockGlobalSettings().UmbracoScriptsPath); Mock.Get(_fileSystems).Setup(x => x.ScriptsFileSystem).Returns(_fileSystem); using (var stream = CreateStream("Umbraco.Sys.registerNamespace(\"Umbraco.Utils\");")) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs index 2e8682d181..a1f0662ebd 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.SetUp(); _fileSystems = Mock.Of(); - _fileSystem = new PhysicalFileSystem(new GlobalSettings(IOHelper).UmbracoCssPath, IOHelper); + _fileSystem = new PhysicalFileSystem(SettingsForTests.GenerateMockGlobalSettings().UmbracoCssPath); Mock.Get(_fileSystems).Setup(x => x.StylesheetsFileSystem).Returns(_fileSystem); var stream = CreateStream("body {background:#EE7600; color:#FFF;}"); _fileSystem.AddFile("styles.css", stream); diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 5752219a93..ad9756fa6b 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -69,8 +69,8 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = RegisterFactory.Create(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var container = TestHelper.GetRegister(); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index bb1b0e4b10..b3ec8dd08b 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -23,8 +23,8 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var register = RegisterFactory.Create(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var register = TestHelper.GetRegister(); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); register.Register(_ => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GetDefaultUmbracoSettings()))); diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 360df5daeb..f1042519f5 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -176,9 +176,9 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var register = RegisterFactory.Create(); + var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.WithCollectionBuilder() .Append() diff --git a/src/Umbraco.Tests/Published/ModelTypeTests.cs b/src/Umbraco.Tests/Published/ModelTypeTests.cs index 622bebdf78..1dab67b351 100644 --- a/src/Umbraco.Tests/Published/ModelTypeTests.cs +++ b/src/Umbraco.Tests/Published/ModelTypeTests.cs @@ -53,7 +53,7 @@ namespace Umbraco.Tests.Published // there's an "*" there because the arrays are not true SZArray - but that changes when we map Assert.AreEqual("{alias1}[*]", ModelType.For("alias1").MakeArrayType().FullName); // note the inner assembly qualified name - Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[{alias1}[*], Umbraco.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]", typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1").MakeArrayType()).FullName); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[{alias1}[*], Umbraco.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=null]]", typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1").MakeArrayType()).FullName); } [Test] diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs index 86cba62bd9..31cfcb7dc8 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs @@ -55,10 +55,9 @@ namespace Umbraco.Tests.PublishedContent var factory = Mock.Of(); Current.Factory = factory; - var configs = new Configs(); + var configs = TestHelper.GetConfigs(); Mock.Get(factory).Setup(x => x.GetInstance(typeof(Configs))).Returns(configs); - - var globalSettings = new GlobalSettings(Mock.Of()); + var globalSettings = new GlobalSettings(IOHelper.Default); configs.Add(SettingsForTests.GenerateMockUmbracoSettings); configs.Add(() => globalSettings); @@ -1119,7 +1118,7 @@ namespace Umbraco.Tests.PublishedContent _snapshotService.Notify(new[] { - new ContentCacheRefresher.JsonPayload(1, Guid.Empty, TreeChangeTypes.RefreshNode) + new ContentCacheRefresher.JsonPayload(1, Guid.Empty, TreeChangeTypes.RefreshNode) }, out _, out _); Assert.AreEqual(2, contentStore.Test.LiveGen); @@ -1139,7 +1138,7 @@ namespace Umbraco.Tests.PublishedContent /// 2) Save and publish it /// 3) Publish it with descendants /// 4) Repeat steps 2 and 3 - /// + /// /// Which has caused an exception. To replicate this test: /// 1) RefreshBranch with kits for a branch where the top most node is unpublished /// 2) RefreshBranch with kits for the branch where the top most node is published @@ -1167,7 +1166,7 @@ namespace Umbraco.Tests.PublishedContent //children of 1 yield return CreateInvariantKit(20, 1, 1, paths); - yield return CreateInvariantKit(30, 1, 2, paths); + yield return CreateInvariantKit(30, 1, 2, paths); yield return CreateInvariantKit(40, 1, 3, paths); } @@ -1204,12 +1203,12 @@ namespace Umbraco.Tests.PublishedContent var (gen, contentNode) = contentStore.Test.GetValues(1)[0]; Assert.AreEqual(assertGen, gen); //even when unpublishing/re-publishing/etc... the linked list is always maintained - AssertLinkedNode(contentNode, 100, 2, 3, 20, 40); + AssertLinkedNode(contentNode, 100, 2, 3, 20, 40); } //unpublish the root ChangePublishFlagOfRoot(false, 2, TreeChangeTypes.RefreshBranch); - + //publish the root (since it's not published, it will cause a RefreshBranch) ChangePublishFlagOfRoot(true, 3, TreeChangeTypes.RefreshBranch); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index 81cee15869..25ff5e233b 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -50,9 +50,9 @@ namespace Umbraco.Tests.PublishedContent var factory = Mock.Of(); Current.Factory = factory; - var configs = new Configs(); + var configs = TestHelper.GetConfigs(); Mock.Get(factory).Setup(x => x.GetInstance(typeof(Configs))).Returns(configs); - var globalSettings = new GlobalSettings(Mock.Of()); + var globalSettings = new GlobalSettings(IOHelper.Default); configs.Add(SettingsForTests.GenerateMockUmbracoSettings); configs.Add(() => globalSettings); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index d0e780a92b..882db8112c 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -48,7 +48,7 @@ namespace Umbraco.Tests.PublishedContent { var baseLoader = base.CreateTypeLoader(ioHelper, typeFinder, runtimeCache, globalSettings, logger); - return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(globalSettings.LocalTempPath), logger, false, + return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(globalSettings.LocalTempPath(ioHelper)), logger, false, // this is so the model factory looks into the test assembly baseLoader.AssembliesToScan .Union(new[] {typeof(PublishedContentMoreTests).Assembly}) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 7c70e82047..de4dd45f64 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -91,7 +91,7 @@ namespace Umbraco.Tests.PublishedContent { var baseLoader = base.CreateTypeLoader(ioHelper, typeFinder, runtimeCache, globalSettings, logger); - return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(globalSettings.LocalTempPath), logger, false, + return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(globalSettings.LocalTempPath(ioHelper)), logger, false, // this is so the model factory looks into the test assembly baseLoader.AssembliesToScan .Union(new[] { typeof(PublishedContentTests).Assembly }) diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index ac402ad77d..cfc42d3670 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -19,6 +19,7 @@ using Umbraco.Core.Strings; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; +using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Services; @@ -49,11 +50,11 @@ namespace Umbraco.Tests.Routing public class TestRuntime : WebRuntime { - public TestRuntime(UmbracoApplicationBase umbracoApplication) - : base(umbracoApplication) - { } + public TestRuntime(UmbracoApplicationBase umbracoApplication, Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger) + : base(umbracoApplication, configs, umbracoVersion, ioHelper, Mock.Of()) + { + } - protected override ILogger GetLogger() => Mock.Of(); protected override IProfiler GetProfiler() => Mock.Of(); } diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index e95fdfc87c..aed4dba493 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -32,8 +32,9 @@ namespace Umbraco.Tests.Routing //create the module var logger = Mock.Of(); var globalSettings = TestObjects.GetGlobalSettings(); + var umbracoVersion = TestHelper.GetUmbracoVersion(); var runtime = new RuntimeState(logger, Mock.Of(), globalSettings, - new Lazy(), new Lazy()); + new Lazy(), new Lazy(), umbracoVersion); _module = new UmbracoInjectedModule ( @@ -62,7 +63,7 @@ namespace Umbraco.Tests.Routing // do not test for /base here as it's handled before EnsureUmbracoRoutablePage is called [TestCase("/umbraco_client/Tree/treeIcons.css", false)] - [TestCase("/umbraco_client/Tree/Themes/umbraco/style.css?cdv=37", false)] + [TestCase("/umbraco_client/Tree/Themes/umbraco/style.css?cdv=37", false)] [TestCase("/umbraco/editContent.aspx", false)] [TestCase("/install/default.aspx", false)] [TestCase("/install/?installStep=license", false)] diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 5850153100..93c931c93d 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -4,6 +4,7 @@ using System.Data; using System.Web.Hosting; using Examine; using Moq; +using NPoco.Expressions; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Compose; @@ -11,6 +12,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; @@ -78,18 +80,34 @@ namespace Umbraco.Tests.Runtimes // test application public class TestUmbracoApplication : UmbracoApplicationBase { + public TestUmbracoApplication() : base(new DebugDiagnosticsLogger(new MessageTemplates()), GetConfigs()) + { + } + + private static Configs GetConfigs() + { + var configs = new ConfigsFactory(IOHelper.Default).Create(); + configs.Add(SettingsForTests.GetDefaultGlobalSettings); + configs.Add(SettingsForTests.GetDefaultUmbracoSettings); + return configs; + } + public IRuntime Runtime { get; private set; } - protected override IRuntime GetRuntime() + protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger) { - return Runtime = new TestRuntime(); + return Runtime = new TestRuntime(configs, umbracoVersion, ioHelper, logger); } } // test runtime public class TestRuntime : CoreRuntime { - protected override ILogger GetLogger() => new DebugDiagnosticsLogger(); + public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger) + :base(configs, umbracoVersion, ioHelper, logger) + { + + } protected override IProfiler GetProfiler() => new TestProfiler(); // must override the database factory @@ -102,14 +120,6 @@ namespace Umbraco.Tests.Runtimes return mock.Object; } - protected override Configs GetConfigs() - { - var configs = new Configs(); - configs.Add(SettingsForTests.GetDefaultGlobalSettings); - configs.Add(SettingsForTests.GetDefaultUmbracoSettings); - return configs; - } - // FIXME: so how the f* should we do it now? /* // pretend we have the proper migration diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 7ff2e6e7b8..119211225a 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -56,25 +56,26 @@ namespace Umbraco.Tests.Runtimes // FIXME: we need a better management of settings here (and, true config files?) // create the very basic and essential things we need - var logger = new ConsoleLogger(); + var logger = new ConsoleLogger(new MessageTemplates()); var profiler = new LogProfiler(logger); var profilingLogger = new ProfilingLogger(logger, profiler); var appCaches = AppCaches.Disabled; - var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(() => factory.GetInstance())); + var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(() => factory.GetInstance()), TestHelper.GetConfigs()); var typeFinder = new TypeFinder(logger); var ioHelper = IOHelper.Default; var typeLoader = new TypeLoader(ioHelper, typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger); var mainDom = new SimpleMainDom(); - var runtimeState = new RuntimeState(logger, null, null, new Lazy(() => mainDom), new Lazy(() => factory.GetInstance())); + var umbracoVersion = TestHelper.GetUmbracoVersion(); + var runtimeState = new RuntimeState(logger, null, null, new Lazy(() => mainDom), new Lazy(() => factory.GetInstance()), umbracoVersion); + var configs = TestHelper.GetConfigs(); // create the register and the composition - var register = RegisterFactory.Create(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper); + var register = TestHelper.GetRegister(); + var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion); // create the core runtime and have it compose itself - var coreRuntime = new CoreRuntime(); - coreRuntime.Compose(composition); + var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger);coreRuntime.Compose(composition); // determine actual runtime level runtimeState.DetermineRuntimeLevel(databaseFactory, logger); @@ -246,7 +247,7 @@ namespace Umbraco.Tests.Runtimes // - assigning the factory to Current.Factory // create the very basic and essential things we need - var logger = new ConsoleLogger(); + var logger = new ConsoleLogger(new MessageTemplates()); var profiler = Mock.Of(); var profilingLogger = new ProfilingLogger(logger, profiler); var appCaches = AppCaches.Disabled; @@ -258,14 +259,16 @@ namespace Umbraco.Tests.Runtimes Mock.Get(runtimeState).Setup(x => x.Level).Returns(RuntimeLevel.Run); var mainDom = Mock.Of(); Mock.Get(mainDom).Setup(x => x.IsMainDom).Returns(true); + var configs = TestHelper.GetConfigs(); // create the register and the composition - var register = RegisterFactory.Create(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper); + var register = TestHelper.GetRegister(); + var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs); + var umbracoVersion = TestHelper.GetUmbracoVersion(); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion); // create the core runtime and have it compose itself - var coreRuntime = new CoreRuntime(); + var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger); coreRuntime.Compose(composition); // get the components diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs index 3664717af7..27abca7cbd 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Scheduling [OneTimeSetUp] public void InitializeFixture() { - _logger = new DebugDiagnosticsLogger(); + _logger = new DebugDiagnosticsLogger(new MessageTemplates()); } [Test] diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs index 8e886d7dc9..6a65f3afbc 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Scheduling [Timeout(4000)] public async Task ThreadResumeIssue() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger); var work = new ThreadResumeIssueWorkItem(); runner.Add(work); @@ -76,7 +76,7 @@ namespace Umbraco.Tests.Scheduling [Ignore("Only runs in the debugger.")] public async Task DebuggerInterferenceIssue() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger); var taskCompleted = false; runner.TaskCompleted += (sender, args) => diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 44984047f1..708f0d29db 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -30,9 +30,9 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var register = RegisterFactory.Create(); + var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); _testObjects = new TestObjects(register); diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 968698b3b6..9f55fe2e45 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Services private static IProfilingLogger GetTestProfilingLogger() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var profiler = new TestProfiler(); return new ProfilingLogger(logger, profiler); } @@ -268,7 +268,7 @@ namespace Umbraco.Tests.Services var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, tRepository, AppCaches); var languageRepository = new LanguageRepository((IScopeAccessor)provider, AppCaches.Disabled, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository, languageRepository); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository, languageRepository); var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository); // Act diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 57d6b67af8..7bcd3790d4 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -20,6 +20,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Tests.LegacyXmlPublishedCache; +using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; @@ -40,7 +41,7 @@ namespace Umbraco.Tests.Services base.SetUp(); // HACK: but we have no choice until we remove the SavePassword method from IMemberService - var providerMock = new Mock(ServiceContext.MemberService, ServiceContext.MemberTypeService) { CallBase = true }; + var providerMock = new Mock(ServiceContext.MemberService, ServiceContext.MemberTypeService, TestHelper.GetUmbracoVersion()) { CallBase = true }; providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false); providerMock.Setup(@base => @base.PasswordFormat).Returns(MembershipPasswordFormat.Hashed); var provider = providerMock.Object; diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs index 9cf38e1789..0ac6eeb863 100644 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ b/src/Umbraco.Tests/Services/PerformanceTests.cs @@ -60,7 +60,7 @@ namespace Umbraco.Tests.Services private static IProfilingLogger GetTestProfilingLogger() { - var logger = new DebugDiagnosticsLogger(); + var logger = new DebugDiagnosticsLogger(new MessageTemplates()); var profiler = new TestProfiler(); return new ProfilingLogger(logger, profiler); } diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index e1e987c4bf..140759c3bd 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.TestHelpers { Current.Reset(); - var container = RegisterFactory.Create(); + var container = TestHelper.GetRegister(); var ioHelper = IOHelper.Default; var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); @@ -45,7 +45,7 @@ namespace Umbraco.Tests.TestHelpers logger, false); - var composition = new Composition(container, typeLoader, Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + var composition = new Composition(container, typeLoader, Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); composition.RegisterUnique(_ => Mock.Of()); composition.RegisterUnique(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs b/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs index a3e36db363..53d6078e4b 100644 --- a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs +++ b/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs @@ -5,6 +5,13 @@ namespace Umbraco.Tests.TestHelpers { public class ConsoleLogger : ILogger { + private readonly IMessageTemplates _messageTemplates; + + public ConsoleLogger(IMessageTemplates messageTemplates) + { + _messageTemplates = messageTemplates; + } + public bool IsEnabled(Type reporting, LogLevel level) => true; @@ -27,13 +34,13 @@ namespace Umbraco.Tests.TestHelpers public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("FATAL {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); Console.WriteLine(exception); } public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("FATAL {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); } public void Error(Type reporting, Exception exception, string message) @@ -55,13 +62,13 @@ namespace Umbraco.Tests.TestHelpers public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("ERROR {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); Console.WriteLine(exception); } public void Error(Type reporting, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("ERROR {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); } public void Warn(Type reporting, string message) @@ -71,7 +78,7 @@ namespace Umbraco.Tests.TestHelpers public void Warn(Type reporting, string message, params object[] propertyValues) { - Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues)); + Console.WriteLine("WARN {0} - {1}", reporting.Name, _messageTemplates.Render(message, propertyValues)); } public void Warn(Type reporting, Exception exception, string message) @@ -82,13 +89,13 @@ namespace Umbraco.Tests.TestHelpers public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues) { - Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues)); + Console.WriteLine("WARN {0} - {1}", reporting.Name, _messageTemplates.Render(message, propertyValues)); Console.WriteLine(exception); } public void Info(Type reporting, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("INFO {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("INFO {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); } public void Info(Type reporting, string message) @@ -103,7 +110,7 @@ namespace Umbraco.Tests.TestHelpers public void Debug(Type reporting, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("DEBUG {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("DEBUG {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); } public void Verbose(Type reporting, string message) @@ -113,7 +120,7 @@ namespace Umbraco.Tests.TestHelpers public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues) { - Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues)); + Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, _messageTemplates.Render(messageTemplate, propertyValues)); } } } diff --git a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs index d04ad98f6d..a81a1062fc 100644 --- a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs +++ b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs @@ -15,14 +15,14 @@ namespace Umbraco.Tests.TestHelpers { var config = Mock.Of( settings => - settings.ConfigurationStatus == UmbracoVersion.SemanticVersion.ToSemanticString() && + settings.ConfigurationStatus == TestHelper.GetUmbracoVersion().SemanticVersion.ToSemanticString() && settings.UseHttps == false && settings.HideTopLevelNodeFromPath == false && settings.Path == Current.IOHelper.ResolveUrl("~/umbraco") && settings.TimeOutInMinutes == 20 && settings.DefaultUILanguage == "en" && settings.LocalTempStorageLocation == LocalTempStorage.Default && - settings.LocalTempPath == Current.IOHelper.MapPath("~/App_Data/TEMP") && + //settings.LocalTempPath == Current.IOHelper.MapPath("~/App_Data/TEMP") && settings.ReservedPaths == (GlobalSettings.StaticReservedPaths + "~/umbraco") && settings.ReservedUrls == GlobalSettings.StaticReservedUrls && settings.UmbracoPath == "~/umbraco" && diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 671d7fe8ab..9bcbf687d4 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; -using System.Configuration; using System.IO; using System.Linq; using System.Reflection; @@ -34,6 +33,16 @@ namespace Umbraco.Tests.TestHelpers return new TypeLoader(IOHelper.Default, Mock.Of(), Mock.Of(), new DirectoryInfo(IOHelper.Default.MapPath("~/App_Data/TEMP")), Mock.Of()); } + public static Configs GetConfigs() + { + return GetConfigsFactory().Create(); + } + + public static IConfigsFactory GetConfigsFactory() + { + return new ConfigsFactory(IOHelper.Default); + } + /// /// Gets the current assembly directory. /// @@ -64,12 +73,12 @@ namespace Umbraco.Tests.TestHelpers public static void InitializeContentDirectories() { - CreateDirectories(new[] { Constants.SystemDirectories.MvcViews, new GlobalSettings(IOHelper.Default).UmbracoMediaPath, Constants.SystemDirectories.AppPlugins }); + CreateDirectories(new[] { Constants.SystemDirectories.MvcViews, SettingsForTests.GenerateMockGlobalSettings().UmbracoMediaPath, Constants.SystemDirectories.AppPlugins }); } public static void CleanContentDirectories() { - CleanDirectories(new[] { Constants.SystemDirectories.MvcViews, new GlobalSettings(IOHelper.Default).UmbracoMediaPath }); + CleanDirectories(new[] { Constants.SystemDirectories.MvcViews, SettingsForTests.GenerateMockGlobalSettings().UmbracoMediaPath }); } public static void CreateDirectories(string[] directories) @@ -264,5 +273,16 @@ namespace Umbraco.Tests.TestHelpers ); } + + + public static IUmbracoVersion GetUmbracoVersion() + { + return new UmbracoVersion(GetConfigs().Global()); + } + + public static IRegister GetRegister() + { + return RegisterFactory.Create(GetConfigs().Global()); + } } } diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 1962a0085b..d06951d3be 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -240,7 +240,7 @@ namespace Umbraco.Tests.TestHelpers // mappersBuilder.AddCore(); // var mappers = mappersBuilder.CreateCollection(); var mappers = Current.Factory.GetInstance(); - databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, logger, new Lazy(() => mappers)); + databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, logger, new Lazy(() => mappers), TestHelper.GetConfigs()); } typeFinder = typeFinder ?? new TypeFinder(logger); @@ -248,5 +248,6 @@ namespace Umbraco.Tests.TestHelpers var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, logger, typeFinder); return scopeProvider; } + } } diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 050de4fcb9..9ced8d8a5d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -132,7 +132,7 @@ namespace Umbraco.Tests.TestHelpers // ensure the configuration matches the current version for tests var globalSettingsMock = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettingsMock.Setup(x => x.ConfigurationStatus).Returns(UmbracoVersion.Current.ToString(3)); + globalSettingsMock.Setup(x => x.ConfigurationStatus).Returns(Current.UmbracoVersion.Current.ToString(3)); using (ProfilingLogger.TraceDuration("Initialize database.")) { diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 1dec01a4e9..85e57df451 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -100,6 +100,7 @@ namespace Umbraco.Tests.Testing protected ILogger Logger => Factory.GetInstance(); protected IIOHelper IOHelper { get; private set; } + protected IUmbracoVersion UmbracoVersion { get; private set; } protected ITypeFinder TypeFinder { get; private set; } @@ -134,17 +135,20 @@ namespace Umbraco.Tests.Testing var (logger, profiler) = GetLoggers(Options.Logger); var proflogger = new ProfilingLogger(logger, profiler); IOHelper = Umbraco.Core.IO.IOHelper.Default; + TypeFinder = new TypeFinder(logger); var appCaches = GetAppCaches(); var globalSettings = SettingsForTests.GetDefaultGlobalSettings(); + UmbracoVersion = new UmbracoVersion(globalSettings); var typeLoader = GetTypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, globalSettings, proflogger, Options.TypeLoader); - var register = RegisterFactory.Create(); + var register = TestHelper.GetRegister(); - Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs()); Composition.RegisterUnique(IOHelper); + Composition.RegisterUnique(UmbracoVersion); Composition.RegisterUnique(TypeFinder); Composition.RegisterUnique(typeLoader); Composition.RegisterUnique(logger); @@ -200,7 +204,7 @@ namespace Umbraco.Tests.Testing profiler = new LogProfiler(logger); break; case UmbracoTestOptions.Logger.Console: - logger = new ConsoleLogger(); + logger = new ConsoleLogger(new MessageTemplates()); profiler = new LogProfiler(logger); break; default: @@ -297,7 +301,7 @@ namespace Umbraco.Tests.Testing // common to all tests = cannot be overriden private static TypeLoader CreateCommonTypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { - return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(globalSettings.LocalTempPath), logger, false, new[] + return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(globalSettings.LocalTempPath(ioHelper)), logger, false, new[] { Assembly.Load("Umbraco.Core"), Assembly.Load("Umbraco.Web"), @@ -358,7 +362,8 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, Logger, - new Lazy(f.GetInstance))); + new Lazy(f.GetInstance), + TestHelper.GetConfigs())); Composition.RegisterUnique(f => f.TryGetInstance().SqlContext); Composition.WithCollectionBuilder(); // empty @@ -375,7 +380,8 @@ namespace Umbraco.Tests.Testing // somehow property editor ends up wanting this Composition.WithCollectionBuilder(); - Composition.RegisterUnique(); + + Composition.RegisterUnique(); // note - don't register collections, use builders Composition.WithCollectionBuilder(); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 75abcc4d88..80df5f24c5 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -106,6 +106,7 @@ + @@ -552,6 +553,10 @@ {29aa69d9-b597-4395-8d42-43b1263c240a} Umbraco.Abstractions + + {fbe7c065-dac0-4025-a78b-63b24d3ab00b} + Umbraco.Configuration + {31785BC3-256C-4613-B2F5-A1B0BDDED8C1} Umbraco.Core diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 741c1bc9d1..803029b081 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -351,9 +351,6 @@ 9000 / http://localhost:9000/ - 8600 - / - http://localhost:8600/ False False diff --git a/src/Umbraco.Web.UI/web.Template.Debug.config b/src/Umbraco.Web.UI/web.Template.Debug.config index ad76664924..c7c662a184 100644 --- a/src/Umbraco.Web.UI/web.Template.Debug.config +++ b/src/Umbraco.Web.UI/web.Template.Debug.config @@ -13,14 +13,6 @@ file everytime Umbraco builds. --> - -
-
- - - - - diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 91faf2c8c7..8335b80286 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -11,8 +11,8 @@
-
-
+
+
diff --git a/src/Umbraco.Web/AppBuilderExtensions.cs b/src/Umbraco.Web/AppBuilderExtensions.cs index 04226d81f2..f740d57b79 100644 --- a/src/Umbraco.Web/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/AppBuilderExtensions.cs @@ -9,6 +9,7 @@ using Microsoft.Owin.Logging; using Owin; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Web.Composing; using Umbraco.Web.SignalR; namespace Umbraco.Web @@ -50,7 +51,7 @@ namespace Umbraco.Web /// public static IAppBuilder UseSignalR(this IAppBuilder app, IGlobalSettings globalSettings) { - var umbracoPath = globalSettings.GetUmbracoMvcArea(); + var umbracoPath = globalSettings.GetUmbracoMvcArea(Current.IOHelper); var signalrPath = HttpRuntime.AppDomainAppVirtualPath + umbracoPath + "/BackOffice/signalr"; return app.MapSignalR(signalrPath, new HubConfiguration { EnableDetailedErrors = true }); } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 026dedca7d..a3cdc599a3 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -227,6 +227,7 @@ namespace Umbraco.Web.Composing public static IVariationContextAccessor VariationContextAccessor => CoreCurrent.VariationContextAccessor; public static IIOHelper IOHelper => CoreCurrent.IOHelper; + public static IUmbracoVersion UmbracoVersion => CoreCurrent.UmbracoVersion; #endregion } diff --git a/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs b/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs index 4e86b407b5..0561cc06f0 100644 --- a/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs +++ b/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.ContentApps // get the manifest parser just-in-time - injecting it in the ctor would mean that // simply getting the builder in order to configure the collection, would require // its dependencies too, and that can create cycles or other oddities - var manifestParser = factory.GetInstance(); + var manifestParser = factory.GetInstance(); return base.CreateItems(factory).Concat(manifestParser.Manifest.ContentApps.Select(x => new ManifestContentAppFactory(x, Current.IOHelper))); } diff --git a/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs b/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs index 36a417e957..d790b04d46 100644 --- a/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs +++ b/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Dashboards // get the manifest parser just-in-time - injecting it in the ctor would mean that // simply getting the builder in order to configure the collection, would require // its dependencies too, and that can create cycles or other oddities - var manifestParser = factory.GetInstance(); + var manifestParser = factory.GetInstance(); var dashboardSections = Merge(base.CreateItems(factory), manifestParser.Manifest.Dashboards); diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index a2d6a594b2..42386faa20 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -514,7 +514,7 @@ namespace Umbraco.Web.Editors var action = urlHelper.Action("ValidatePasswordResetCode", "BackOffice", new { - area = GlobalSettings.GetUmbracoMvcArea(), + area = GlobalSettings.GetUmbracoMvcArea(Current.IOHelper), u = userId, r = code }); diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index e77a1b70f2..1276cc41d5 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -39,13 +39,13 @@ namespace Umbraco.Web.Editors [DisableBrowserCache] public class BackOfficeController : UmbracoController { - private readonly ManifestParser _manifestParser; + private readonly IManifestParser _manifestParser; private readonly UmbracoFeatures _features; private readonly IRuntimeState _runtimeState; private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; - public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + public BackOfficeController(IManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger, umbracoHelper) { _manifestParser = manifestParser; @@ -352,7 +352,7 @@ namespace Umbraco.Web.Editors if (defaultResponse == null) throw new ArgumentNullException("defaultResponse"); if (externalSignInResponse == null) throw new ArgumentNullException("externalSignInResponse"); - ViewData.SetUmbracoPath(GlobalSettings.GetUmbracoMvcArea()); + ViewData.SetUmbracoPath(GlobalSettings.GetUmbracoMvcArea(Current.IOHelper)); //check if there is the TempData with the any token name specified, if so, assign to view bag and render the view if (ViewData.FromTempData(TempData, ViewDataExtensions.TokenExternalSignInError) || diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 43d0bd3b6b..1b963f1a62 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -442,10 +442,10 @@ namespace Umbraco.Web.Editors // add versions - see UmbracoVersion for details & differences // the complete application version (eg "8.1.2-alpha.25") - { "version", UmbracoVersion.SemanticVersion.ToSemanticString() }, + { "version", Current.UmbracoVersion.SemanticVersion.ToSemanticString() }, // the assembly version (eg "8.0.0") - { "assemblyVersion", UmbracoVersion.AssemblyVersion.ToString() } + { "assemblyVersion", Current.UmbracoVersion.AssemblyVersion.ToString() } }; var version = _runtimeState.SemanticVersion.ToSemanticString(); diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index eef0b5df93..cfa92003bd 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Net; using System.Text; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Logging; @@ -51,7 +52,7 @@ namespace Umbraco.Web.Editors var user = Security.CurrentUser; var allowedSections = string.Join(",", user.AllowedSections); var language = user.Language; - var version = UmbracoVersion.SemanticVersion.ToSemanticString(); + var version = Current.UmbracoVersion.SemanticVersion.ToSemanticString(); var url = string.Format(baseUrl + "{0}?section={0}&allowed={1}&lang={2}&version={3}", section, allowedSections, language, version); var key = "umbraco-dynamic-dashboard-" + language + allowedSections.Replace(",", "-") + section; diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 2381867616..2768af3782 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -1031,7 +1031,7 @@ namespace Umbraco.Web.Editors .SelectMany(x => x.PropertyTypes) .DistinctBy(composition => composition.Alias); var filteredPropertyTypes = ExecutePostFilter(propertyTypes, postFilter); - return Mapper.MapEnumerable(filteredPropertyTypes); + return Mapper.MapEnumerable(filteredPropertyTypes); case UmbracoEntityTypes.PropertyGroup: diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 7dc4008d91..932a86c082 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -118,7 +118,7 @@ namespace Umbraco.Web.Editors if (ins.UmbracoVersionRequirementsType == RequirementsType.Strict) { var packageMinVersion = ins.UmbracoVersion; - if (UmbracoVersion.Current < packageMinVersion) + if (Current.UmbracoVersion.Current < packageMinVersion) { model.IsCompatible = false; } @@ -215,7 +215,7 @@ namespace Umbraco.Web.Editors { var packageFile = await Services.PackagingService.FetchPackageFileAsync( Guid.Parse(packageGuid), - UmbracoVersion.Current, + Current.UmbracoVersion.Current, Security.GetUserId().ResultOr(0)); fileName = packageFile.Name; @@ -259,7 +259,7 @@ namespace Umbraco.Web.Editors if (packageInfo.UmbracoVersionRequirementsType == RequirementsType.Strict) { var packageMinVersion = packageInfo.UmbracoVersion; - if (UmbracoVersion.Current < packageMinVersion) + if (Current.UmbracoVersion.Current < packageMinVersion) throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse( Services.TextService.Localize("packager/targetVersionMismatch", new[] {packageMinVersion.ToString()}))); } @@ -366,7 +366,7 @@ namespace Umbraco.Web.Editors //bump cdf to be safe var clientDependencyConfig = new ClientDependencyConfiguration(Logger); var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber( - UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); + Current.UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); var redirectUrl = ""; if (!packageInfo.PackageView.IsNullOrWhiteSpace()) diff --git a/src/Umbraco.Web/Editors/UpdateCheckController.cs b/src/Umbraco.Web/Editors/UpdateCheckController.cs index 132526576b..b3f8676821 100644 --- a/src/Umbraco.Web/Editors/UpdateCheckController.cs +++ b/src/Umbraco.Web/Editors/UpdateCheckController.cs @@ -26,10 +26,10 @@ namespace Umbraco.Web.Editors { var check = new org.umbraco.update.CheckForUpgrade { Timeout = 2000 }; - var result = check.CheckUpgrade(UmbracoVersion.Current.Major, - UmbracoVersion.Current.Minor, - UmbracoVersion.Current.Build, - UmbracoVersion.Comment); + var result = check.CheckUpgrade(Current.UmbracoVersion.Current.Major, + Current.UmbracoVersion.Current.Minor, + Current.UmbracoVersion.Current.Build, + Current.UmbracoVersion.Comment); return new UpgradeCheckResponse(result.UpgradeType.ToString(), result.Comment, result.UpgradeUrl); } diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs index e30054df78..c2519d434d 100644 --- a/src/Umbraco.Web/Editors/UsersController.cs +++ b/src/Umbraco.Web/Editors/UsersController.cs @@ -456,7 +456,7 @@ namespace Umbraco.Web.Editors var action = urlHelper.Action("VerifyInvite", "BackOffice", new { - area = GlobalSettings.GetUmbracoMvcArea(), + area = GlobalSettings.GetUmbracoMvcArea(Current.IOHelper), invite = inviteToken }); diff --git a/src/Umbraco.Web/Install/Controllers/InstallController.cs b/src/Umbraco.Web/Install/Controllers/InstallController.cs index 4b99c2ccba..96583cf4e0 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallController.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Install.Controllers // Update ClientDependency version var clientDependencyConfig = new ClientDependencyConfiguration(_logger); var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber( - UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); + Current.UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); // Delete ClientDependency temp directories to make sure we get fresh caches var clientDependencyTempFilesDeleted = clientDependencyConfig.ClearTempFiles(HttpContext); diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index effb46c9b7..46efb69124 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Configuration; -using System.IO; using System.Linq; using System.Net.Http; using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; @@ -24,15 +21,17 @@ namespace Umbraco.Web.Install private readonly HttpContextBase _httpContext; private readonly ILogger _logger; private readonly IGlobalSettings _globalSettings; + private readonly IUmbracoVersion _umbracoVersion; private InstallationType? _installationType; public InstallHelper(IUmbracoContextAccessor umbracoContextAccessor, DatabaseBuilder databaseBuilder, - ILogger logger, IGlobalSettings globalSettings) + ILogger logger, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion) { _httpContext = umbracoContextAccessor.UmbracoContext.HttpContext; _logger = logger; _globalSettings = globalSettings; + _umbracoVersion = umbracoVersion; _databaseBuilder = databaseBuilder; } @@ -75,10 +74,10 @@ namespace Umbraco.Web.Install IsBrandNewInstall == false, isCompleted, DateTime.Now, - UmbracoVersion.Current.Major, - UmbracoVersion.Current.Minor, - UmbracoVersion.Current.Build, - UmbracoVersion.Comment, + _umbracoVersion.Current.Major, + _umbracoVersion.Current.Minor, + _umbracoVersion.Current.Build, + _umbracoVersion.Comment, errorMsg, userAgent, dbProvider); @@ -113,9 +112,9 @@ namespace Umbraco.Web.Install { get { - var databaseSettings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName]; + var databaseSettings = Current.Configs.ConnectionStrings()[Constants.System.UmbracoConnectionName]; if (_globalSettings.ConfigurationStatus.IsNullOrWhiteSpace() - && _databaseBuilder.IsConnectionStringConfigured(databaseSettings) == false) + && databaseSettings.IsConnectionStringConfigured() == false) { //no version or conn string configured, must be a brand new install return true; @@ -123,7 +122,7 @@ namespace Umbraco.Web.Install //now we have to check if this is really a new install, the db might be configured and might contain data - if (_databaseBuilder.IsConnectionStringConfigured(databaseSettings) == false + if (databaseSettings.IsConnectionStringConfigured() == false || _databaseBuilder.IsDatabaseConfigured == false) { return true; @@ -141,7 +140,7 @@ namespace Umbraco.Web.Install var packages = new List(); try { - var requestUri = $"https://our.umbraco.com/webapi/StarterKit/Get/?umbracoVersion={UmbracoVersion.Current}"; + var requestUri = $"https://our.umbraco.com/webapi/StarterKit/Get/?umbracoVersion={_umbracoVersion.Current}"; using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri)) { diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs index d119759488..8d1e161811 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs @@ -1,7 +1,7 @@ using System; -using System.Configuration; using System.Threading.Tasks; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Web.Install.Models; @@ -72,9 +72,9 @@ namespace Umbraco.Web.Install.InstallSteps private bool ShouldDisplayView() { //If the connection string is already present in web.config we don't need to show the settings page and we jump to installing/upgrading. - var databaseSettings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName]; + var databaseSettings = Current.Configs.ConnectionStrings()[Constants.System.UmbracoConnectionName]; - if (_databaseBuilder.IsConnectionStringConfigured(databaseSettings)) + if (databaseSettings.IsConnectionStringConfigured()) { try { diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs index c680b6e41a..7d8c7f1226 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs @@ -6,6 +6,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; +using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -55,7 +56,7 @@ namespace Umbraco.Web.Install.InstallSteps // Remove legacy umbracoDbDsn configuration setting if it exists and connectionstring also exists if (ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName] != null) { - GlobalSettings.RemoveSetting(Constants.System.UmbracoConnectionName); + GlobalSettings.RemoveSetting(Constants.System.UmbracoConnectionName, Current.IOHelper); } else { diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs index 4e8068c4c5..4a61ce3a70 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs @@ -1,13 +1,11 @@ -using System; -using System.Configuration; -using System.Linq; +using System.Linq; using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Migrations.Upgrade; +using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; -using Umbraco.Web.Migrations; using Umbraco.Web.Migrations.PostMigrations; namespace Umbraco.Web.Install.InstallSteps @@ -66,9 +64,9 @@ namespace Umbraco.Web.Install.InstallSteps return false; } - var databaseSettings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName]; + var databaseSettings = Current.Configs.ConnectionStrings()[Constants.System.UmbracoConnectionName]; - if (_databaseBuilder.IsConnectionStringConfigured(databaseSettings)) + if (databaseSettings.IsConnectionStringConfigured()) { // a connection string was present, determine whether this is an install/upgrade // return true (upgrade) if there is an installed version, else false (install) diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs index 151265f394..15d14574ed 100644 --- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Specialized; -using System.Configuration; -using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -135,13 +133,13 @@ namespace Umbraco.Web.Install.InstallSteps public override bool RequiresExecution(UserModel model) { //now we have to check if this is really a new install, the db might be configured and might contain data - var databaseSettings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName]; + var databaseSettings = Current.Configs.ConnectionStrings()[Constants.System.UmbracoConnectionName]; //if there's already a version then there should def be a user but in some cases someone may have // left a version number in there but cleared out their db conn string, in that case, it's really a new install. if (_globalSettings.ConfigurationStatus.IsNullOrWhiteSpace() == false && databaseSettings != null) return false; - if (_databaseBuilder.IsConnectionStringConfigured(databaseSettings) && _databaseBuilder.IsDatabaseConfigured) + if (databaseSettings.IsConnectionStringConfigured() && _databaseBuilder.IsDatabaseConfigured) return _databaseBuilder.HasSomeNonDefaultUser() == false; // In this one case when it's a brand new install and nothing has been configured, make sure the diff --git a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs index b5fdea32b7..3187953989 100644 --- a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs @@ -21,15 +21,15 @@ namespace Umbraco.Web.Install.InstallSteps private readonly InstallHelper _installHelper; private readonly IGlobalSettings _globalSettings; private readonly IUserService _userService; - private readonly DistributedCache _distributedCache; + private readonly IUmbracoVersion _umbracoVersion; - public SetUmbracoVersionStep(HttpContextBase httpContext, InstallHelper installHelper, IGlobalSettings globalSettings, IUserService userService, DistributedCache distributedCache) + public SetUmbracoVersionStep(HttpContextBase httpContext, InstallHelper installHelper, IGlobalSettings globalSettings, IUserService userService, IUmbracoVersion umbracoVersion) { _httpContext = httpContext; _installHelper = installHelper; _globalSettings = globalSettings; _userService = userService; - _distributedCache = distributedCache; + _umbracoVersion = umbracoVersion; } public override Task ExecuteAsync(object model) @@ -61,7 +61,7 @@ namespace Umbraco.Web.Install.InstallSteps } // Update configurationStatus - _globalSettings.ConfigurationStatus = UmbracoVersion.SemanticVersion.ToSemanticString(); + _globalSettings.ConfigurationStatus = _umbracoVersion.SemanticVersion.ToSemanticString(); //reports the ended install _installHelper.InstallStatus(true, ""); diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index 78b58a509e..624f5897c7 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -19,13 +19,15 @@ namespace Umbraco.Web.Install.InstallSteps { private readonly InstallHelper _installHelper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IUmbracoVersion _umbracoVersion; private readonly IContentService _contentService; private readonly IPackagingService _packageService; - public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IUmbracoContextAccessor umbracoContextAccessor) + public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoVersion umbracoVersion) { _installHelper = installHelper; _umbracoContextAccessor = umbracoContextAccessor; + _umbracoVersion = umbracoVersion; _contentService = contentService; _packageService = packageService; } @@ -64,7 +66,7 @@ namespace Umbraco.Web.Install.InstallSteps private async Task<(string packageFile, int packageId)> DownloadPackageFilesAsync(Guid kitGuid) { //Go get the package file from the package repo - var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, UmbracoVersion.Current, _umbracoContextAccessor.UmbracoContext.Security.GetUserId().ResultOr(0)); + var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, _umbracoVersion.Current, _umbracoContextAccessor.UmbracoContext.Security.GetUserId().ResultOr(0)); if (packageFile == null) throw new InvalidOperationException("Could not fetch package file " + kitGuid); //add an entry to the installedPackages.config diff --git a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs index 3cab550a87..23a3c9062d 100644 --- a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs @@ -25,9 +25,9 @@ namespace Umbraco.Web.Install.InstallSteps // that was a "normal" way to force the upgrader to execute, and we would detect the current // version via the DB like DatabaseSchemaResult.DetermineInstalledVersion - magic, do we really // need this now? - var currentVersion = (UmbracoVersion.LocalVersion ?? new Semver.SemVersion(0)).ToString(); + var currentVersion = (Current.UmbracoVersion.LocalVersion ?? new Semver.SemVersion(0)).ToString(); - var newVersion = UmbracoVersion.SemanticVersion.ToString(); + var newVersion = Current.UmbracoVersion.SemanticVersion.ToString(); string FormatGuidState(string value) { diff --git a/src/Umbraco.Web/JavaScript/CssInitialization.cs b/src/Umbraco.Web/JavaScript/CssInitialization.cs index 172244038d..8cf9067606 100644 --- a/src/Umbraco.Web/JavaScript/CssInitialization.cs +++ b/src/Umbraco.Web/JavaScript/CssInitialization.cs @@ -10,9 +10,9 @@ namespace Umbraco.Web.JavaScript { internal class CssInitialization : AssetInitialization { - private readonly ManifestParser _parser; + private readonly IManifestParser _parser; - public CssInitialization(ManifestParser parser) + public CssInitialization(IManifestParser parser) { _parser = parser; } diff --git a/src/Umbraco.Web/JavaScript/JsInitialization.cs b/src/Umbraco.Web/JavaScript/JsInitialization.cs index c2fe6b7631..30772137e0 100644 --- a/src/Umbraco.Web/JavaScript/JsInitialization.cs +++ b/src/Umbraco.Web/JavaScript/JsInitialization.cs @@ -19,9 +19,9 @@ namespace Umbraco.Web.JavaScript ///
internal class JsInitialization : AssetInitialization { - private readonly ManifestParser _parser; + private readonly IManifestParser _parser; - public JsInitialization(ManifestParser parser) + public JsInitialization(IManifestParser parser) { _parser = parser; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs index 528d5f6de5..05a8ecc97e 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Models.Mapping mapper.Define((source, context) => new MediaTypeDisplay(), Map); mapper.Define((source, context) => new MemberTypeDisplay(), Map); - mapper.Define( + mapper.Define( (source, context) => { var dataType = _dataTypeService.GetDataType(source.DataTypeId); @@ -216,7 +216,7 @@ namespace Umbraco.Web.Models.Mapping // Umbraco.Code.MapAll -CreateDate -DeleteDate -UpdateDate // Umbraco.Code.MapAll -SupportsPublishing -Key -PropertyEditorAlias -ValueStorageType - private static void Map(PropertyTypeBasic source, PropertyType target, MapperContext context) + private static void Map(PropertyTypeBasic source, IPropertyType target, MapperContext context) { target.Name = source.Label; target.DataTypeId = source.DataTypeId; @@ -610,9 +610,9 @@ namespace Umbraco.Web.Models.Mapping return destGroup; } - private static PropertyType MapSaveProperty(PropertyTypeBasic sourceProperty, IEnumerable destOrigProperties, MapperContext context) + private static IPropertyType MapSaveProperty(PropertyTypeBasic sourceProperty, IEnumerable destOrigProperties, MapperContext context) { - PropertyType destProperty; + IPropertyType destProperty; if (sourceProperty.Id > 0) { // updating an existing property @@ -631,11 +631,11 @@ namespace Umbraco.Web.Models.Mapping // insert a new property, or update an existing property that has // been deleted in the meantime and we need to re-create // map/create - destProperty = context.Map(sourceProperty); + destProperty = context.Map(sourceProperty); return destProperty; } - private static void EnsureUniqueAliases(IEnumerable properties) + private static void EnsureUniqueAliases(IEnumerable properties) { var propertiesA = properties.ToArray(); var distinctProperties = propertiesA diff --git a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs index 540b080dbc..b7ebd49ac5 100644 --- a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs @@ -194,7 +194,7 @@ namespace Umbraco.Web.Models.Mapping return groups.OrderBy(x => x.SortOrder); } - private IEnumerable MapProperties(IEnumerable properties, IContentTypeBase contentType, int groupId, bool inherited) + private IEnumerable MapProperties(IEnumerable properties, IContentTypeBase contentType, int groupId, bool inherited) { var mappedProperties = new List(); diff --git a/src/Umbraco.Web/Models/UpgradeCheckResponse.cs b/src/Umbraco.Web/Models/UpgradeCheckResponse.cs index df384a51cd..ddbeac4989 100644 --- a/src/Umbraco.Web/Models/UpgradeCheckResponse.cs +++ b/src/Umbraco.Web/Models/UpgradeCheckResponse.cs @@ -5,6 +5,7 @@ using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using System.Web; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; namespace Umbraco.Web.Models @@ -26,7 +27,7 @@ namespace Umbraco.Web.Models { Type = upgradeType; Comment = upgradeComment; - Url = upgradeUrl + "?version=" + HttpUtility.UrlEncode(UmbracoVersion.Current.ToString(3)); + Url = upgradeUrl + "?version=" + HttpUtility.UrlEncode(Current.UmbracoVersion.Current.ToString(3)); } } } diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index 61a659615f..8b4f84c2dd 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -7,6 +7,7 @@ using System.Web.SessionState; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; +using Umbraco.Web.Composing; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc @@ -55,7 +56,7 @@ namespace Umbraco.Web.Mvc if (routes == null) throw new ArgumentNullException(nameof(routes)); if (defaultId == null) throw new ArgumentNullException(nameof(defaultId)); - var umbracoArea = globalSettings.GetUmbracoMvcArea(); + var umbracoArea = globalSettings.GetUmbracoMvcArea(Current.IOHelper); //routes are explicitly named with controller names and IDs var url = umbracoArea + "/" + diff --git a/src/Umbraco.Web/Mvc/BackOfficeArea.cs b/src/Umbraco.Web/Mvc/BackOfficeArea.cs index e72f2cc81a..5f257a9860 100644 --- a/src/Umbraco.Web/Mvc/BackOfficeArea.cs +++ b/src/Umbraco.Web/Mvc/BackOfficeArea.cs @@ -1,4 +1,5 @@ using System.Web.Mvc; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Web.Editors; @@ -26,15 +27,16 @@ namespace Umbraco.Web.Mvc /// public override void RegisterArea(AreaRegistrationContext context) { + context.MapRoute( "Umbraco_preview", - _globalSettings.GetUmbracoMvcArea() + "/preview/{action}/{editor}", + AreaName + "/preview/{action}/{editor}", new {controller = "Preview", action = "Index", editor = UrlParameter.Optional}, new[] { "Umbraco.Web.Editors" }); context.MapRoute( "Umbraco_back_office", - _globalSettings.GetUmbracoMvcArea() + "/{action}/{id}", + AreaName + "/{action}/{id}", new {controller = "BackOffice", action = "Default", id = UrlParameter.Optional}, //limit the action/id to only allow characters - this is so this route doesn't hog all other // routes like: /umbraco/channels/word.aspx, etc... @@ -46,6 +48,6 @@ namespace Umbraco.Web.Mvc new[] {typeof (BackOfficeController).Namespace}); } - public override string AreaName => _globalSettings.GetUmbracoMvcArea(); + public override string AreaName => _globalSettings.GetUmbracoMvcArea(Current.IOHelper); } } diff --git a/src/Umbraco.Web/Profiling/WebProfilingController.cs b/src/Umbraco.Web/Profiling/WebProfilingController.cs index b3d580bc38..a8935da033 100644 --- a/src/Umbraco.Web/Profiling/WebProfilingController.cs +++ b/src/Umbraco.Web/Profiling/WebProfilingController.cs @@ -1,4 +1,10 @@ -using Umbraco.Web.Editors; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; +using Umbraco.Web.Editors; using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Profiling @@ -9,11 +15,19 @@ namespace Umbraco.Web.Profiling [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)] public class WebProfilingController : UmbracoAuthorizedJsonController { + private readonly IRuntimeState _runtimeState; + + public WebProfilingController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + { + _runtimeState = runtimeState; + } + public object GetStatus() { return new { - Enabled = Core.Configuration.GlobalSettings.DebugMode + Enabled = _runtimeState.Debug }; } }} diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 554e76c665..974731b9bd 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -299,7 +299,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private string GetLocalFilesPath() { - var path = Path.Combine(_globalSettings.LocalTempPath, "NuCache"); + var path = Path.Combine(_globalSettings.LocalTempPath(Current.IOHelper), "NuCache"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index 3b29212598..380c3915b7 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -119,7 +119,7 @@ namespace Umbraco.Web.Runtime // location to be there if (globalSettings.LocalTempStorageLocation == LocalTempStorage.EnvironmentTemp) { - var cachePath = globalSettings.LocalTempPath; + var cachePath = globalSettings.LocalTempPath(Current.IOHelper); //set the file map and composite file default location to the %temp% location BaseCompositeFileProcessingProvider.CompositeFilePathDefaultFolder @@ -150,7 +150,7 @@ namespace Umbraco.Web.Runtime SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes) { - var umbracoPath = globalSettings.GetUmbracoMvcArea(); + var umbracoPath = globalSettings.GetUmbracoMvcArea(Current.IOHelper); // create the front-end route var defaultRoute = RouteTable.Routes.MapRoute( @@ -175,7 +175,7 @@ namespace Umbraco.Web.Runtime SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes) { - var umbracoPath = globalSettings.GetUmbracoMvcArea(); + var umbracoPath = globalSettings.GetUmbracoMvcArea(Current.IOHelper); // need to find the plugin controllers and route them var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray(); diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 2f1ef43e4c..bd17907cc9 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Runtime; using Umbraco.Web.Cache; @@ -24,7 +25,8 @@ namespace Umbraco.Web.Runtime /// Initializes a new instance of the class. ///
/// - public WebRuntime(UmbracoApplicationBase umbracoApplication) + public WebRuntime(UmbracoApplicationBase umbracoApplication, Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger): + base(configs, umbracoVersion, ioHelper, logger) { _umbracoApplication = umbracoApplication; } @@ -33,8 +35,7 @@ namespace Umbraco.Web.Runtime public override IFactory Boot(IRegister register) { // create and start asap to profile boot - var debug = GlobalSettings.DebugMode; - if (debug) + if (State.Debug) { _webProfiler = new WebProfiler(); _webProfiler.Start(); diff --git a/src/Umbraco.Web/Sections/SectionCollectionBuilder.cs b/src/Umbraco.Web/Sections/SectionCollectionBuilder.cs index e38da85cfa..de883db83a 100644 --- a/src/Umbraco.Web/Sections/SectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Sections/SectionCollectionBuilder.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Sections // get the manifest parser just-in-time - injecting it in the ctor would mean that // simply getting the builder in order to configure the collection, would require // its dependencies too, and that can create cycles or other oddities - var manifestParser = factory.GetInstance(); + var manifestParser = factory.GetInstance(); return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections); } diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index fff16cf314..656b4a4c66 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -2,6 +2,7 @@ using System.Configuration.Provider; using System.Web.Security; using Umbraco.Core; +using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Security; using Umbraco.Core.Services; @@ -16,11 +17,11 @@ namespace Umbraco.Web.Security.Providers public class MembersMembershipProvider : UmbracoMembershipProvider, IUmbracoMemberTypeMembershipProvider { public MembersMembershipProvider() - : this(Current.Services.MemberService, Current.Services.MemberTypeService) + : this(Current.Services.MemberService, Current.Services.MemberTypeService, Current.UmbracoVersion) { } - public MembersMembershipProvider(IMembershipMemberService memberService, IMemberTypeService memberTypeService) - : base(memberService) + public MembersMembershipProvider(IMembershipMemberService memberService, IMemberTypeService memberTypeService, IUmbracoVersion umbracoVersion) + : base(memberService, umbracoVersion) { LockPropertyTypeAlias = Constants.Conventions.Member.IsLockedOut; LastLockedOutPropertyTypeAlias = Constants.Conventions.Member.LastLockoutDate; diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs index 1f7e2c8084..06b221288c 100644 --- a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs @@ -27,11 +27,13 @@ namespace Umbraco.Web.Security.Providers where T : IMembershipMemberService where TEntity : class, IMembershipUser { + private readonly IUmbracoVersion _umbracoVersion; protected IMembershipMemberService MemberService { get; private set; } - protected UmbracoMembershipProvider(IMembershipMemberService memberService) + protected UmbracoMembershipProvider(IMembershipMemberService memberService, IUmbracoVersion umbracoVersion) { + _umbracoVersion = umbracoVersion; MemberService = memberService; } @@ -355,7 +357,7 @@ namespace Umbraco.Web.Security.Providers // http://issues.umbraco.org/issue/U4-3451 // when upgrading from 7.2 to 7.3 trying to save will throw - if (UmbracoVersion.Current >= new Version(7, 3, 0, 0)) + if (_umbracoVersion.Current >= new Version(7, 3, 0, 0)) MemberService.Save(member, false); } @@ -595,7 +597,7 @@ namespace Umbraco.Web.Security.Providers // for this type of thing (i.e. UpdateLastLogin or similar). // when upgrading from 7.2 to 7.3 trying to save will throw - if (UmbracoVersion.Current >= new Version(7, 3, 0, 0)) + if (_umbracoVersion.Current >= new Version(7, 3, 0, 0)) MemberService.Save(member, false); return new ValidateUserResult diff --git a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs index f3aa5dd838..9d169414bb 100644 --- a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs @@ -21,12 +21,12 @@ namespace Umbraco.Web.Security.Providers { public UsersMembershipProvider() - : this(Current.Services.UserService, Current.Services.MemberTypeService) + : this(Current.Services.UserService, Current.Services.MemberTypeService, Current.UmbracoVersion) { } - public UsersMembershipProvider(IMembershipMemberService memberService, IMemberTypeService memberTypeService) - : base(memberService) + public UsersMembershipProvider(IMembershipMemberService memberService, IMemberTypeService memberTypeService, IUmbracoVersion umbracoVersion) + : base(memberService, umbracoVersion) { _memberTypeService = memberTypeService; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b5478d4d38..a732dfeb10 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -103,6 +103,10 @@ {29aa69d9-b597-4395-8d42-43b1263c240a} Umbraco.Abstractions + + {fbe7c065-dac0-4025-a78b-63b24d3ab00b} + Umbraco.Configuration + {31785bc3-256c-4613-b2f5-a1b0bdded8c1} Umbraco.Core @@ -1283,4 +1287,4 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 191fb9dcd6..ec620cdb8d 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -1,6 +1,9 @@ using System.Threading; using System.Web; using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Web.Runtime; namespace Umbraco.Web @@ -10,9 +13,9 @@ namespace Umbraco.Web ///
public class UmbracoApplication : UmbracoApplicationBase { - protected override IRuntime GetRuntime() + protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger) { - return new WebRuntime(this); + return new WebRuntime(this, configs, umbracoVersion, ioHelper, logger); } /// diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 59b5b1779b..c0e56579b6 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -5,6 +5,8 @@ using System.Web; using System.Web.Hosting; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; @@ -17,17 +19,36 @@ namespace Umbraco.Web { private IRuntime _runtime; + public readonly ILogger _logger; + private readonly Configs _configs; + private readonly IIOHelper _ioHelper; + + protected UmbracoApplicationBase() + { + _logger = SerilogLogger.CreateWithDefaultConfiguration(); + _ioHelper = IOHelper.Default; + _configs = new ConfigsFactory(_ioHelper).Create(); + } + + protected UmbracoApplicationBase(ILogger logger, Configs configs) + { + _logger = logger; + _configs = configs; + _ioHelper = IOHelper.Default; + } + + /// /// Gets a runtime. /// - protected abstract IRuntime GetRuntime(); + protected abstract IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger); /// /// Gets the application register. /// - protected virtual IRegister GetRegister() + protected virtual IRegister GetRegister(IGlobalSettings globalSettings) { - return RegisterFactory.Create(); + return RegisterFactory.Create(globalSettings); } // events - in the order they trigger @@ -58,10 +79,14 @@ namespace Umbraco.Web { // ******** THIS IS WHERE EVERYTHING BEGINS ******** + + var globalSettings = _configs.Global(); + var umbracoVersion = new UmbracoVersion(globalSettings); + // create the register for the application, and boot // the boot manager is responsible for registrations - var register = GetRegister(); - _runtime = GetRuntime(); + var register = GetRegister(globalSettings); + _runtime = GetRuntime(_configs, umbracoVersion, _ioHelper, _logger); _runtime.Boot(register); } diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 347f79e51b..547bd517d8 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -4,6 +4,7 @@ using System.IO; using System.Web; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; @@ -173,7 +174,7 @@ namespace Umbraco.Web { var request = GetRequestFromContext(); //NOTE: the request can be null during app startup! - return GlobalSettings.DebugMode + return Current.RuntimeState.Debug && request != null && (string.IsNullOrEmpty(request["umbdebugshowtrace"]) == false || string.IsNullOrEmpty(request["umbdebug"]) == false @@ -290,7 +291,7 @@ namespace Umbraco.Web _previewing = _previewToken.IsNullOrWhiteSpace() == false; } - + // say we render a macro or RTE in a give 'preview' mode that might not be the 'current' one, // then due to the way it all works at the moment, the 'current' published snapshot need to be in the proper // default 'preview' mode - somehow we have to force it. and that could be recursive. diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs index 249ce76193..243f327c9a 100644 --- a/src/Umbraco.Web/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/UrlHelperExtensions.cs @@ -143,7 +143,7 @@ namespace Umbraco.Web //in case the user bypasses the installer and just bumps the web.config or client dependency config //if in debug mode, always burst the cache - if (GlobalSettings.DebugMode) + if (Current.RuntimeState.Debug) { return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash(); } diff --git a/src/umbraco.sln b/src/umbraco.sln index b89daf1925..c70f10bdb3 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -1,7 +1,4 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2005 -Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29209.152 MinimumVisualStudioVersion = 10.0.40219.1 @@ -111,6 +108,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.ModelsBuilder.Embed EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Infrastructure", "Umbraco.Infrastructure\Umbraco.Infrastructure.csproj", "{3AE7BF57-966B-45A5-910A-954D7C554441}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Configuration", "Umbraco.Configuration\Umbraco.Configuration.csproj", "{FBE7C065-DAC0-4025-A78B-63B24D3AB00B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -155,6 +154,10 @@ Global {3AE7BF57-966B-45A5-910A-954D7C554441}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AE7BF57-966B-45A5-910A-954D7C554441}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AE7BF57-966B-45A5-910A-954D7C554441}.Release|Any CPU.Build.0 = Release|Any CPU + {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE