diff --git a/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs b/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs index 0d33378669..acd2281a1e 100644 --- a/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs +++ b/src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs @@ -6,5 +6,7 @@ namespace Umbraco.Core.Configuration { get; } + + void RemoveConnectionString(string umbracoConnectionName); } } diff --git a/src/Umbraco.Web/Features/DisabledFeatures.cs b/src/Umbraco.Abstractions/Features/DisabledFeatures.cs similarity index 82% rename from src/Umbraco.Web/Features/DisabledFeatures.cs rename to src/Umbraco.Abstractions/Features/DisabledFeatures.cs index 62fb019c70..9bd091a570 100644 --- a/src/Umbraco.Web/Features/DisabledFeatures.cs +++ b/src/Umbraco.Abstractions/Features/DisabledFeatures.cs @@ -1,5 +1,4 @@ using Umbraco.Core.Collections; -using Umbraco.Web.WebApi; namespace Umbraco.Web.Features { @@ -13,19 +12,19 @@ namespace Umbraco.Web.Features /// public DisabledFeatures() { - Controllers = new TypeList(); + Controllers = new TypeList(); } /// /// Gets the disabled controllers. /// - public TypeList Controllers { get; } + public TypeList Controllers { get; } /// /// Disables the device preview feature of previewing. /// public bool DisableDevicePreview { get; set; } - + /// /// If true, all references to templates will be removed in the back office and routing /// diff --git a/src/Umbraco.Web/Features/EnabledFeatures.cs b/src/Umbraco.Abstractions/Features/EnabledFeatures.cs similarity index 100% rename from src/Umbraco.Web/Features/EnabledFeatures.cs rename to src/Umbraco.Abstractions/Features/EnabledFeatures.cs diff --git a/src/Umbraco.Abstractions/Features/IUmbracoFeatureController.cs b/src/Umbraco.Abstractions/Features/IUmbracoFeatureController.cs new file mode 100644 index 0000000000..0187cdecb0 --- /dev/null +++ b/src/Umbraco.Abstractions/Features/IUmbracoFeatureController.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Web.Features +{ + public interface IUmbracoFeature + { + + } +} diff --git a/src/Umbraco.Web/Features/UmbracoFeatures.cs b/src/Umbraco.Abstractions/Features/UmbracoFeatures.cs similarity index 90% rename from src/Umbraco.Web/Features/UmbracoFeatures.cs rename to src/Umbraco.Abstractions/Features/UmbracoFeatures.cs index d1c3899271..69fe58f76d 100644 --- a/src/Umbraco.Web/Features/UmbracoFeatures.cs +++ b/src/Umbraco.Abstractions/Features/UmbracoFeatures.cs @@ -1,5 +1,4 @@ using System; -using Umbraco.Web.WebApi; namespace Umbraco.Web.Features { @@ -16,7 +15,7 @@ namespace Umbraco.Web.Features Disabled = new DisabledFeatures(); Enabled = new EnabledFeatures(); } - + /// /// Gets the disabled features. /// @@ -32,7 +31,7 @@ namespace Umbraco.Web.Features /// internal bool IsControllerEnabled(Type feature) { - if (typeof(UmbracoApiControllerBase).IsAssignableFrom(feature)) + if (typeof(IUmbracoFeature).IsAssignableFrom(feature)) return Disabled.Controllers.Contains(feature) == false; throw new NotSupportedException("Not a supported feature type."); diff --git a/src/Umbraco.Web/IUmbracoContextFactory.cs b/src/Umbraco.Abstractions/IUmbracoContextFactory.cs similarity index 100% rename from src/Umbraco.Web/IUmbracoContextFactory.cs rename to src/Umbraco.Abstractions/IUmbracoContextFactory.cs diff --git a/src/Umbraco.Web/Install/InstallException.cs b/src/Umbraco.Abstractions/Install/InstallException.cs similarity index 100% rename from src/Umbraco.Web/Install/InstallException.cs rename to src/Umbraco.Abstractions/Install/InstallException.cs diff --git a/src/Umbraco.Web/Install/InstallStatusTracker.cs b/src/Umbraco.Abstractions/Install/InstallStatusTracker.cs similarity index 69% rename from src/Umbraco.Web/Install/InstallStatusTracker.cs rename to src/Umbraco.Abstractions/Install/InstallStatusTracker.cs index 58e8507ec8..c0c9a696fd 100644 --- a/src/Umbraco.Web/Install/InstallStatusTracker.cs +++ b/src/Umbraco.Abstractions/Install/InstallStatusTracker.cs @@ -2,10 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Collections; -using Umbraco.Web.Composing; +using Umbraco.Core.IO; +using Umbraco.Core.Serialization; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install @@ -13,29 +13,37 @@ namespace Umbraco.Web.Install /// /// An internal in-memory status tracker for the current installation /// - internal static class InstallStatusTracker + public class InstallStatusTracker { + private readonly IIOHelper _ioHelper; + private readonly IJsonSerializer _jsonSerializer; + + public InstallStatusTracker(IIOHelper ioHelper, IJsonSerializer jsonSerializer) + { + _ioHelper = ioHelper; + _jsonSerializer = jsonSerializer; + } private static ConcurrentHashSet _steps = new ConcurrentHashSet(); - private static string GetFile(Guid installId) + private string GetFile(Guid installId) { - var file = Current.IOHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/" - + "install_" - + installId.ToString("N") - + ".txt"); + var file = _ioHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/" + + "install_" + + installId.ToString("N") + + ".txt"); return file; } - public static void Reset() + public void Reset() { _steps = new ConcurrentHashSet(); ClearFiles(); } - public static void ClearFiles() + public void ClearFiles() { - var dir = Current.IOHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/"); + var dir = _ioHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/"); if (Directory.Exists(dir)) { var files = Directory.GetFiles(dir); @@ -50,13 +58,13 @@ namespace Umbraco.Web.Install } } - public static IEnumerable InitializeFromFile(Guid installId) + public IEnumerable InitializeFromFile(Guid installId) { //check if we have our persisted file and read it var file = GetFile(installId); if (File.Exists(file)) { - var deserialized = JsonConvert.DeserializeObject>( + var deserialized = _jsonSerializer.Deserialize>( File.ReadAllText(file)); foreach (var item in deserialized) { @@ -70,7 +78,7 @@ namespace Umbraco.Web.Install return new List(_steps); } - public static IEnumerable Initialize(Guid installId, IEnumerable steps) + public IEnumerable Initialize(Guid installId, IEnumerable steps) { //if there are no steps in memory if (_steps.Count == 0) @@ -79,7 +87,7 @@ namespace Umbraco.Web.Install var file = GetFile(installId); if (File.Exists(file)) { - var deserialized = JsonConvert.DeserializeObject>( + var deserialized = _jsonSerializer.Deserialize>( File.ReadAllText(file)); foreach (var item in deserialized) { @@ -96,7 +104,7 @@ namespace Umbraco.Web.Install _steps.Add(new InstallTrackingItem(step.Name, step.ServerOrder)); } //save the file - var serialized = JsonConvert.SerializeObject(new List(_steps)); + var serialized = _jsonSerializer.Serialize(new List(_steps)); Directory.CreateDirectory(Path.GetDirectoryName(file)); File.WriteAllText(file, serialized); } @@ -110,7 +118,7 @@ namespace Umbraco.Web.Install ClearFiles(); //save the correct file - var serialized = JsonConvert.SerializeObject(new List(_steps)); + var serialized = _jsonSerializer.Serialize(new List(_steps)); Directory.CreateDirectory(Path.GetDirectoryName(file)); File.WriteAllText(file, serialized); } @@ -119,7 +127,7 @@ namespace Umbraco.Web.Install return new List(_steps); } - public static void SetComplete(Guid installId, string name, IDictionary additionalData = null) + public void SetComplete(Guid installId, string name, IDictionary additionalData = null) { var trackingItem = _steps.Single(x => x.Name == name); if (additionalData != null) @@ -130,7 +138,7 @@ namespace Umbraco.Web.Install //save the file var file = GetFile(installId); - var serialized = JsonConvert.SerializeObject(new List(_steps)); + var serialized = _jsonSerializer.Serialize(new List(_steps)); File.WriteAllText(file, serialized); } diff --git a/src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs b/src/Umbraco.Abstractions/Install/InstallSteps/FilePermissionsStep.cs similarity index 98% rename from src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs rename to src/Umbraco.Abstractions/Install/InstallSteps/FilePermissionsStep.cs index b4be0b0a21..c3d7493084 100644 --- a/src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs +++ b/src/Umbraco.Abstractions/Install/InstallSteps/FilePermissionsStep.cs @@ -4,7 +4,6 @@ using System.IO; using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Install; -using Umbraco.Core.IO; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs b/src/Umbraco.Abstractions/Install/InstallSteps/StarterKitCleanupStep.cs similarity index 100% rename from src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs rename to src/Umbraco.Abstractions/Install/InstallSteps/StarterKitCleanupStep.cs diff --git a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs b/src/Umbraco.Abstractions/Install/InstallSteps/UpgradeStep.cs similarity index 84% rename from src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs rename to src/Umbraco.Abstractions/Install/InstallSteps/UpgradeStep.cs index a59d7394f0..0979f31dc5 100644 --- a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs +++ b/src/Umbraco.Abstractions/Install/InstallSteps/UpgradeStep.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Umbraco.Web.Composing; +using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Web.Install.Models; @@ -14,10 +14,12 @@ namespace Umbraco.Web.Install.InstallSteps { public override bool RequiresExecution(object model) => true; private readonly IUmbracoVersion _umbracoVersion; + private readonly IRuntimeState _runtimeState; - public UpgradeStep(IUmbracoVersion umbracoVersion) + public UpgradeStep(IUmbracoVersion umbracoVersion, IRuntimeState runtimeState) { _umbracoVersion = umbracoVersion; + _runtimeState = runtimeState; } public override Task ExecuteAsync(object model) => Task.FromResult(null); @@ -43,9 +45,9 @@ namespace Umbraco.Web.Install.InstallSteps return value; } - var state = Current.RuntimeState; // TODO: inject - var currentState = FormatGuidState(state.CurrentMigrationState); - var newState = FormatGuidState(state.FinalMigrationState); + + var currentState = FormatGuidState(_runtimeState.CurrentMigrationState); + var newState = FormatGuidState(_runtimeState.FinalMigrationState); var reportUrl = $"https://our.umbraco.com/contribute/releases/compare?from={currentVersion}&to={newVersion}¬es=1"; diff --git a/src/Umbraco.Web/Install/Models/DatabaseModel.cs b/src/Umbraco.Abstractions/Install/Models/DatabaseModel.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/DatabaseModel.cs rename to src/Umbraco.Abstractions/Install/Models/DatabaseModel.cs diff --git a/src/Umbraco.Web/Install/Models/DatabaseType.cs b/src/Umbraco.Abstractions/Install/Models/DatabaseType.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/DatabaseType.cs rename to src/Umbraco.Abstractions/Install/Models/DatabaseType.cs diff --git a/src/Umbraco.Web/Install/Models/InstallInstructions.cs b/src/Umbraco.Abstractions/Install/Models/InstallInstructions.cs similarity index 80% rename from src/Umbraco.Web/Install/Models/InstallInstructions.cs rename to src/Umbraco.Abstractions/Install/Models/InstallInstructions.cs index da4dfb1671..159edda9e6 100644 --- a/src/Umbraco.Web/Install/Models/InstallInstructions.cs +++ b/src/Umbraco.Abstractions/Install/Models/InstallInstructions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; -using Newtonsoft.Json.Linq; namespace Umbraco.Web.Install.Models { @@ -9,7 +8,7 @@ namespace Umbraco.Web.Install.Models public class InstallInstructions { [DataMember(Name = "instructions")] - public IDictionary Instructions { get; set; } + public IDictionary Instructions { get; set; } [DataMember(Name = "installId")] public Guid InstallId { get; set; } diff --git a/src/Umbraco.Web/Install/Models/InstallProgressResultModel.cs b/src/Umbraco.Abstractions/Install/Models/InstallProgressResultModel.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/InstallProgressResultModel.cs rename to src/Umbraco.Abstractions/Install/Models/InstallProgressResultModel.cs diff --git a/src/Umbraco.Web/Install/Models/InstallSetup.cs b/src/Umbraco.Abstractions/Install/Models/InstallSetup.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/InstallSetup.cs rename to src/Umbraco.Abstractions/Install/Models/InstallSetup.cs diff --git a/src/Umbraco.Web/Install/Models/InstallSetupResult.cs b/src/Umbraco.Abstractions/Install/Models/InstallSetupResult.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/InstallSetupResult.cs rename to src/Umbraco.Abstractions/Install/Models/InstallSetupResult.cs diff --git a/src/Umbraco.Web/Install/Models/InstallSetupStep.cs b/src/Umbraco.Abstractions/Install/Models/InstallSetupStep.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/InstallSetupStep.cs rename to src/Umbraco.Abstractions/Install/Models/InstallSetupStep.cs diff --git a/src/Umbraco.Web/Install/Models/InstallSetupStepAttribute.cs b/src/Umbraco.Abstractions/Install/Models/InstallSetupStepAttribute.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/InstallSetupStepAttribute.cs rename to src/Umbraco.Abstractions/Install/Models/InstallSetupStepAttribute.cs diff --git a/src/Umbraco.Web/Install/Models/InstallTrackingItem.cs b/src/Umbraco.Abstractions/Install/Models/InstallTrackingItem.cs similarity index 96% rename from src/Umbraco.Web/Install/Models/InstallTrackingItem.cs rename to src/Umbraco.Abstractions/Install/Models/InstallTrackingItem.cs index 1b1985dd1e..9bc8201ba9 100644 --- a/src/Umbraco.Web/Install/Models/InstallTrackingItem.cs +++ b/src/Umbraco.Abstractions/Install/Models/InstallTrackingItem.cs @@ -3,7 +3,7 @@ using System.Runtime.Serialization; namespace Umbraco.Web.Install.Models { - internal class InstallTrackingItem + public class InstallTrackingItem { public InstallTrackingItem(string name, int serverOrder) { diff --git a/src/Umbraco.Web/Install/Models/InstallationType.cs b/src/Umbraco.Abstractions/Install/Models/InstallationType.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/InstallationType.cs rename to src/Umbraco.Abstractions/Install/Models/InstallationType.cs diff --git a/src/Umbraco.Web/Install/Models/Package.cs b/src/Umbraco.Abstractions/Install/Models/Package.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/Package.cs rename to src/Umbraco.Abstractions/Install/Models/Package.cs diff --git a/src/Umbraco.Web/Install/Models/UserModel.cs b/src/Umbraco.Abstractions/Install/Models/UserModel.cs similarity index 100% rename from src/Umbraco.Web/Install/Models/UserModel.cs rename to src/Umbraco.Abstractions/Install/Models/UserModel.cs diff --git a/src/Umbraco.Abstractions/Trees/IMenuItemCollectionFactory.cs b/src/Umbraco.Abstractions/Trees/IMenuItemCollectionFactory.cs new file mode 100644 index 0000000000..64feba8cd8 --- /dev/null +++ b/src/Umbraco.Abstractions/Trees/IMenuItemCollectionFactory.cs @@ -0,0 +1,9 @@ +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + public interface IMenuItemCollectionFactory + { + MenuItemCollection Create(); + } +} diff --git a/src/Umbraco.Web/Models/Trees/MenuItemCollection.cs b/src/Umbraco.Abstractions/Trees/MenuItemCollection.cs similarity index 72% rename from src/Umbraco.Web/Models/Trees/MenuItemCollection.cs rename to src/Umbraco.Abstractions/Trees/MenuItemCollection.cs index e6a75b15d4..84d46c0d11 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItemCollection.cs +++ b/src/Umbraco.Abstractions/Trees/MenuItemCollection.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Runtime.Serialization; +using Umbraco.Web.Actions; namespace Umbraco.Web.Models.Trees { @@ -9,17 +10,16 @@ namespace Umbraco.Web.Models.Trees [DataContract(Name = "menuItems", Namespace = "")] public class MenuItemCollection { - public static MenuItemCollection Empty => new MenuItemCollection(); + private readonly MenuItemList _menuItems; - private readonly MenuItemList _menuItems = new MenuItemList(); - - public MenuItemCollection() + public MenuItemCollection(ActionCollection actionCollection) { + _menuItems = new MenuItemList(actionCollection); } - public MenuItemCollection(IEnumerable items) + public MenuItemCollection(ActionCollection actionCollection, IEnumerable items) { - _menuItems = new MenuItemList(items); + _menuItems = new MenuItemList(actionCollection, items); } /// diff --git a/src/Umbraco.Abstractions/Trees/MenuItemCollectionFactory.cs b/src/Umbraco.Abstractions/Trees/MenuItemCollectionFactory.cs new file mode 100644 index 0000000000..0a8ea000e3 --- /dev/null +++ b/src/Umbraco.Abstractions/Trees/MenuItemCollectionFactory.cs @@ -0,0 +1,21 @@ +using Umbraco.Web.Actions; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + public class MenuItemCollectionFactory: IMenuItemCollectionFactory + { + private readonly ActionCollection _actionCollection; + + public MenuItemCollectionFactory(ActionCollection actionCollection) + { + _actionCollection = actionCollection; + } + + public MenuItemCollection Create() + { + return new MenuItemCollection(_actionCollection); + } + + } +} diff --git a/src/Umbraco.Web/Models/Trees/MenuItemList.cs b/src/Umbraco.Abstractions/Trees/MenuItemList.cs similarity index 82% rename from src/Umbraco.Web/Models/Trees/MenuItemList.cs rename to src/Umbraco.Abstractions/Trees/MenuItemList.cs index 7bfa5eca48..546fa0390f 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItemList.cs +++ b/src/Umbraco.Abstractions/Trees/MenuItemList.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Umbraco.Core.Services; using Umbraco.Web.Actions; -using Umbraco.Web.Composing; namespace Umbraco.Web.Models.Trees { @@ -13,13 +12,17 @@ namespace Umbraco.Web.Models.Trees /// public class MenuItemList : List { - public MenuItemList() + private readonly ActionCollection _actionCollection; + + public MenuItemList(ActionCollection actionCollection) { + _actionCollection = actionCollection; } - public MenuItemList( IEnumerable items) + public MenuItemList(ActionCollection actionCollection, IEnumerable items) : base(items) { + _actionCollection = actionCollection; } /// @@ -44,7 +47,7 @@ namespace Umbraco.Web.Models.Trees private MenuItem CreateMenuItem(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false) where T : IAction { - var item = Current.Actions.GetAction(); + var item = _actionCollection.GetAction(); if (item == null) return null; var menuItem = new MenuItem(item, textService.Localize($"actions/{item.Alias}")) diff --git a/src/Umbraco.Configuration/ConfigsFactory.cs b/src/Umbraco.Configuration/ConfigsFactory.cs index fea0c23f29..c09dc7b9f6 100644 --- a/src/Umbraco.Configuration/ConfigsFactory.cs +++ b/src/Umbraco.Configuration/ConfigsFactory.cs @@ -7,11 +7,6 @@ namespace Umbraco.Core.Configuration { public class ConfigsFactory : IConfigsFactory { - - public ConfigsFactory() - { - } - public IHostingSettings HostingSettings { get; } = new HostingSettings(); public ICoreDebug CoreDebug { get; } = new CoreDebug(); @@ -32,7 +27,7 @@ namespace Umbraco.Core.Configuration configs.AddPasswordConfigurations(); configs.Add(() => CoreDebug); - configs.Add(() => new ConnectionStrings()); + configs.Add(() => new ConnectionStrings(ioHelper)); configs.AddCoreConfigs(ioHelper); return configs; } diff --git a/src/Umbraco.Configuration/ConnectionStrings.cs b/src/Umbraco.Configuration/ConnectionStrings.cs index 707f58c7b7..6a00974831 100644 --- a/src/Umbraco.Configuration/ConnectionStrings.cs +++ b/src/Umbraco.Configuration/ConnectionStrings.cs @@ -8,6 +8,13 @@ namespace Umbraco.Core.Configuration { public class ConnectionStrings : IConnectionStrings { + private readonly IIOHelper _ioHelper; + + public ConnectionStrings(IIOHelper ioHelper) + { + _ioHelper = ioHelper; + } + public ConfigConnectionString this[string key] { get @@ -17,5 +24,22 @@ namespace Umbraco.Core.Configuration return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name); } } + + public void RemoveConnectionString(string key) + { + 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(); + var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key); + + if (setting != null) + { + setting.Remove(); + xml.Save(fileName, SaveOptions.DisableFormatting); + ConfigurationManager.RefreshSection("appSettings"); + } + var settings = ConfigurationManager.ConnectionStrings[key]; + } } } diff --git a/src/Umbraco.Configuration/GlobalSettings.cs b/src/Umbraco.Configuration/GlobalSettings.cs index 6cd1ea58a5..a44f7ae636 100644 --- a/src/Umbraco.Configuration/GlobalSettings.cs +++ b/src/Umbraco.Configuration/GlobalSettings.cs @@ -254,27 +254,7 @@ namespace Umbraco.Core.Configuration ConfigurationManager.RefreshSection("appSettings"); } - /// - /// Removes a setting from the configuration file. - /// - /// Key of the setting to be removed. - public static void RemoveSetting(string key, IIOHelper ioHelper) - { - 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(); - var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key); - - if (setting != null) - { - setting.Remove(); - xml.Save(fileName, SaveOptions.DisableFormatting); - ConfigurationManager.RefreshSection("appSettings"); - } - } - - + /// /// Gets the time out in minutes. /// diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder.cs similarity index 98% rename from src/Umbraco.Web/Cache/DistributedCacheBinder.cs rename to src/Umbraco.Infrastructure/Cache/DistributedCacheBinder.cs index e56d2bfe88..92ed7de881 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder.cs +++ b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder.cs @@ -4,10 +4,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.Logging; -using Umbraco.Core.Serialization; namespace Umbraco.Web.Cache { diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinderComposer.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs similarity index 100% rename from src/Umbraco.Web/Cache/DistributedCacheBinderComposer.cs rename to src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs similarity index 99% rename from src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs rename to src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs index b9de06c2d3..c0200933ab 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -9,7 +8,6 @@ using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Services.Implement; -using Umbraco.Web.Services; namespace Umbraco.Web.Cache { diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseConfigureStep.cs similarity index 98% rename from src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs rename to src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseConfigureStep.cs index dbf664bc93..3a978cc47a 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseConfigureStep.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web.Install.InstallSteps [InstallSetupStep(InstallationType.NewInstall, "DatabaseConfigure", "database", 10, "Setting up a database, so Umbraco has a place to store your website", PerformsAppRestart = true)] - internal class DatabaseConfigureStep : InstallSetupStep + public class DatabaseConfigureStep : InstallSetupStep { private readonly DatabaseBuilder _databaseBuilder; private readonly ILogger _logger; diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs similarity index 79% rename from src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs rename to src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs index 843b5ff887..a7b3dcc218 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -13,19 +12,21 @@ namespace Umbraco.Web.Install.InstallSteps { [InstallSetupStep(InstallationType.NewInstall | InstallationType.Upgrade, "DatabaseInstall", 11, "")] - internal class DatabaseInstallStep : InstallSetupStep + public class DatabaseInstallStep : InstallSetupStep { private readonly DatabaseBuilder _databaseBuilder; private readonly IRuntimeState _runtime; private readonly ILogger _logger; private readonly IIOHelper _ioHelper; + private readonly IConnectionStrings _connectionStrings; - public DatabaseInstallStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger, IIOHelper ioHelper) + public DatabaseInstallStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings) { _databaseBuilder = databaseBuilder; _runtime = runtime; _logger = logger; _ioHelper = ioHelper; + _connectionStrings = connectionStrings; } public override Task ExecuteAsync(object model) @@ -42,7 +43,7 @@ namespace Umbraco.Web.Install.InstallSteps if (result.RequiresUpgrade == false) { - HandleConnectionStrings(_logger, _ioHelper); + HandleConnectionStrings(_logger, _ioHelper, _connectionStrings); return Task.FromResult(null); } @@ -53,12 +54,18 @@ namespace Umbraco.Web.Install.InstallSteps })); } - internal static void HandleConnectionStrings(ILogger logger, IIOHelper ioHelper) + internal static void HandleConnectionStrings(ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings) { + + + var databaseSettings = connectionStrings[Constants.System.UmbracoConnectionName]; + + + // Remove legacy umbracoDbDsn configuration setting if it exists and connectionstring also exists - if (ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName] != null) + if (databaseSettings != null) { - GlobalSettings.RemoveSetting(Constants.System.UmbracoConnectionName, ioHelper); + connectionStrings.RemoveConnectionString(Constants.System.UmbracoConnectionName); } else { diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs similarity index 97% rename from src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs rename to src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs index 603fbd726c..3cd3c1ca56 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs @@ -7,7 +7,6 @@ using Umbraco.Core.IO; 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.PostMigrations; @@ -15,7 +14,7 @@ namespace Umbraco.Web.Install.InstallSteps { [InstallSetupStep(InstallationType.Upgrade | InstallationType.NewInstall, "DatabaseUpgrade", 12, "")] - internal class DatabaseUpgradeStep : InstallSetupStep + public class DatabaseUpgradeStep : InstallSetupStep { private readonly DatabaseBuilder _databaseBuilder; private readonly IRuntimeState _runtime; @@ -56,7 +55,7 @@ namespace Umbraco.Web.Install.InstallSteps throw new InstallException("The database failed to upgrade. ERROR: " + result.Message); } - DatabaseInstallStep.HandleConnectionStrings(_logger, _ioHelper); + DatabaseInstallStep.HandleConnectionStrings(_logger, _ioHelper, _connectionStrings); } return Task.FromResult(null); diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 2e9df383bf..e2a7d7a5cc 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -23,6 +23,8 @@ using Umbraco.Core.Sync; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.PublishedCache; using Umbraco.Web; +using Umbraco.Web.Install; +using Umbraco.Web.Trees; using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator; namespace Umbraco.Core.Runtime @@ -54,6 +56,8 @@ namespace Umbraco.Core.Runtime composition.RegisterUnique(f => f.GetInstance()); composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); // register database builder // *not* a singleton, don't want to keep it around diff --git a/src/Umbraco.Web/Trees/TreeNode.cs b/src/Umbraco.Infrastructure/Trees/TreeNode.cs similarity index 97% rename from src/Umbraco.Web/Trees/TreeNode.cs rename to src/Umbraco.Infrastructure/Trees/TreeNode.cs index 7661387b3d..cc130b1b97 100644 --- a/src/Umbraco.Web/Trees/TreeNode.cs +++ b/src/Umbraco.Infrastructure/Trees/TreeNode.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; +using Umbraco.Composing; using Umbraco.Core; -using Umbraco.Web.Composing; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Trees @@ -23,7 +23,7 @@ namespace Umbraco.Web.Models.Trees /// The parent id for the current node /// /// - internal TreeNode(string nodeId, string parentId, string getChildNodesUrl, string menuUrl) + public TreeNode(string nodeId, string parentId, string getChildNodesUrl, string menuUrl) { if (nodeId == null) throw new ArgumentNullException(nameof(nodeId)); if (string.IsNullOrWhiteSpace(nodeId)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(nodeId)); diff --git a/src/Umbraco.Web/Models/Trees/TreeNodeCollection.cs b/src/Umbraco.Infrastructure/Trees/TreeNodeCollection.cs similarity index 100% rename from src/Umbraco.Web/Models/Trees/TreeNodeCollection.cs rename to src/Umbraco.Infrastructure/Trees/TreeNodeCollection.cs diff --git a/src/Umbraco.Web/Models/Trees/TreeNodeExtensions.cs b/src/Umbraco.Infrastructure/Trees/TreeNodeExtensions.cs similarity index 100% rename from src/Umbraco.Web/Models/Trees/TreeNodeExtensions.cs rename to src/Umbraco.Infrastructure/Trees/TreeNodeExtensions.cs diff --git a/src/Umbraco.Web/Models/Trees/TreeRootNode.cs b/src/Umbraco.Infrastructure/Trees/TreeRootNode.cs similarity index 100% rename from src/Umbraco.Web/Models/Trees/TreeRootNode.cs rename to src/Umbraco.Infrastructure/Trees/TreeRootNode.cs diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index f10c18492a..255c7d53cf 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -55,7 +55,9 @@ using Umbraco.Core.Models.Identity; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Net; +using Umbraco.Web.Install; using Umbraco.Web.Security; +using Umbraco.Web.Trees; using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Tests.Testing { @@ -412,6 +414,8 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(); Composition.RegisterUnique(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); // register filesystems Composition.RegisterUnique(factory => TestObjects.GetFileSystemsMock()); diff --git a/src/Umbraco.Web/Net/AspNetBackOfficeInfo.cs b/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs similarity index 100% rename from src/Umbraco.Web/Net/AspNetBackOfficeInfo.cs rename to src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs diff --git a/src/Umbraco.Web/Net/AspNetCookieManager.cs b/src/Umbraco.Web/AspNet/AspNetCookieManager.cs similarity index 100% rename from src/Umbraco.Web/Net/AspNetCookieManager.cs rename to src/Umbraco.Web/AspNet/AspNetCookieManager.cs diff --git a/src/Umbraco.Web/Hosting/AspNetHostingEnvironment.cs b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs similarity index 100% rename from src/Umbraco.Web/Hosting/AspNetHostingEnvironment.cs rename to src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs diff --git a/src/Umbraco.Web/Net/AspNetHttpContextAccessor.cs b/src/Umbraco.Web/AspNet/AspNetHttpContextAccessor.cs similarity index 100% rename from src/Umbraco.Web/Net/AspNetHttpContextAccessor.cs rename to src/Umbraco.Web/AspNet/AspNetHttpContextAccessor.cs diff --git a/src/Umbraco.Web/Net/AspNetIpResolver.cs b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs similarity index 100% rename from src/Umbraco.Web/Net/AspNetIpResolver.cs rename to src/Umbraco.Web/AspNet/AspNetIpResolver.cs diff --git a/src/Umbraco.Web/Net/AspNetPasswordHasher.cs b/src/Umbraco.Web/AspNet/AspNetPasswordHasher.cs similarity index 100% rename from src/Umbraco.Web/Net/AspNetPasswordHasher.cs rename to src/Umbraco.Web/AspNet/AspNetPasswordHasher.cs diff --git a/src/Umbraco.Web/Net/AspNetSessionIdResolver.cs b/src/Umbraco.Web/AspNet/AspNetSessionIdResolver.cs similarity index 100% rename from src/Umbraco.Web/Net/AspNetSessionIdResolver.cs rename to src/Umbraco.Web/AspNet/AspNetSessionIdResolver.cs diff --git a/src/Umbraco.Web/FrameworkMarchal.cs b/src/Umbraco.Web/AspNet/FrameworkMarchal.cs similarity index 100% rename from src/Umbraco.Web/FrameworkMarchal.cs rename to src/Umbraco.Web/AspNet/FrameworkMarchal.cs diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 40985e97bf..8d4af6703e 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -27,6 +27,7 @@ using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Services; +using Umbraco.Web.Trees; using Umbraco.Web.WebApi; namespace Umbraco.Web.Composing @@ -260,6 +261,7 @@ namespace Umbraco.Web.Composing public static IIpResolver IpResolver => Factory.GetInstance(); public static IUmbracoVersion UmbracoVersion => Factory.GetInstance(); public static IPublishedUrlProvider PublishedUrlProvider => Factory.GetInstance(); + public static IMenuItemCollectionFactory MenuItemCollectionFactory => Factory.GetInstance(); #endregion } diff --git a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs index d151df46f7..c69766cc9d 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs @@ -20,13 +20,15 @@ namespace Umbraco.Web.Install.Controllers private readonly DatabaseBuilder _databaseBuilder; private readonly IProfilingLogger _proflog; private readonly InstallStepCollection _installSteps; + private readonly InstallStatusTracker _installStatusTracker; private readonly ILogger _logger; - public InstallApiController(DatabaseBuilder databaseBuilder, IProfilingLogger proflog, InstallHelper installHelper, InstallStepCollection installSteps) + public InstallApiController(DatabaseBuilder databaseBuilder, IProfilingLogger proflog, InstallHelper installHelper, InstallStepCollection installSteps, InstallStatusTracker installStatusTracker) { _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog)); _installSteps = installSteps; + _installStatusTracker = installStatusTracker; InstallHelper = installHelper; _logger = _proflog; } @@ -56,7 +58,7 @@ namespace Umbraco.Web.Install.Controllers steps.AddRange(installSteps); setup.Steps = steps; - InstallStatusTracker.Initialize(setup.InstallId, installSteps); + _installStatusTracker.Initialize(setup.InstallId, installSteps); return setup; } @@ -78,7 +80,7 @@ namespace Umbraco.Web.Install.Controllers //there won't be any statuses returned if the app pool has restarted so we need to re-read from file. if (status.Any() == false) { - status = InstallStatusTracker.InitializeFromFile(installModel.InstallId).ToArray(); + status = _installStatusTracker.InitializeFromFile(installModel.InstallId).ToArray(); } //create a new queue of the non-finished ones @@ -95,7 +97,7 @@ namespace Umbraco.Web.Install.Controllers if (StepRequiresExecution(step, instruction) == false) { // set this as complete and continue - InstallStatusTracker.SetComplete(installModel.InstallId, item.Name); + _installStatusTracker.SetComplete(installModel.InstallId, item.Name); continue; } @@ -104,7 +106,7 @@ namespace Umbraco.Web.Install.Controllers var setupData = await ExecuteStepAsync(step, instruction); // update the status - InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData?.SavedStepData); + _installStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData?.SavedStepData); // determine's the next step in the queue and dequeue's any items that don't need to execute var nextStep = IterateSteps(step, queue, installModel.InstallId, installModel); @@ -147,7 +149,7 @@ namespace Umbraco.Web.Install.Controllers } } - InstallStatusTracker.Reset(); + _installStatusTracker.Reset(); return new InstallProgressResultModel(true, "", ""); } @@ -175,7 +177,7 @@ namespace Umbraco.Web.Install.Controllers var step = _installSteps.GetAllSteps().Single(x => x.Name == item.Name); // if this step has any instructions then extract them - JToken instruction; + object instruction; installModel.Instructions.TryGetValue(item.Name, out instruction); // else null // if the step requires execution then return its name @@ -187,7 +189,7 @@ namespace Umbraco.Web.Install.Controllers queue.Dequeue(); // complete - InstallStatusTracker.SetComplete(installId, step.Name); + _installStatusTracker.SetComplete(installId, step.Name); // and continue current = step; @@ -197,9 +199,9 @@ namespace Umbraco.Web.Install.Controllers } // determines whether the step requires execution - internal bool StepRequiresExecution(InstallSetupStep step, JToken instruction) + internal bool StepRequiresExecution(InstallSetupStep step, object instruction) { - var model = instruction?.ToObject(step.StepType); + var model = Convert.ChangeType(instruction, step.StepType); var genericStepType = typeof(InstallSetupStep<>); Type[] typeArgs = { step.StepType }; var typedStepType = genericStepType.MakeGenericType(typeArgs); @@ -216,11 +218,11 @@ namespace Umbraco.Web.Install.Controllers } // executes the step - internal async Task ExecuteStepAsync(InstallSetupStep step, JToken instruction) + internal async Task ExecuteStepAsync(InstallSetupStep step, object instruction) { using (_proflog.TraceDuration($"Executing installation step: '{step.Name}'.", "Step completed")) { - var model = instruction?.ToObject(step.StepType); + var model = Convert.ChangeType(instruction, step.StepType); var genericStepType = typeof(InstallSetupStep<>); Type[] typeArgs = { step.StepType }; var typedStepType = genericStepType.MakeGenericType(typeArgs); diff --git a/src/Umbraco.Web/Install/FilePermissionHelper.cs b/src/Umbraco.Web/Install/FilePermissionHelper.cs index 7fc40a1202..16de66554f 100644 --- a/src/Umbraco.Web/Install/FilePermissionHelper.cs +++ b/src/Umbraco.Web/Install/FilePermissionHelper.cs @@ -7,7 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Install; using Umbraco.Core.IO; -using Umbraco.Web.Composing; +using Umbraco.Web.PublishedCache; namespace Umbraco.Web.Install { @@ -21,11 +21,13 @@ namespace Umbraco.Web.Install private readonly string[] _permissionFiles = { }; private readonly IGlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; + private readonly IPublishedSnapshotService _publishedSnapshotService; - public FilePermissionHelper(IGlobalSettings globalSettings, IIOHelper ioHelper) + public FilePermissionHelper(IGlobalSettings globalSettings, IIOHelper ioHelper, IPublishedSnapshotService publishedSnapshotService) { _globalSettings = globalSettings; _ioHelper = ioHelper; + _publishedSnapshotService = publishedSnapshotService; _permissionDirs = new[] { _globalSettings.UmbracoCssPath, Constants.SystemDirectories.Config, Constants.SystemDirectories.Data, _globalSettings.UmbracoMediaPath, Constants.SystemDirectories.Preview }; _packagesPermissionsDirs = new[] { Constants.SystemDirectories.Bin, _globalSettings.UmbracoPath, Constants.SystemDirectories.Packages }; } @@ -48,7 +50,7 @@ namespace Umbraco.Web.Install if (TestPublishedSnapshotService(out errors) == false) report["Published snapshot environment check failed"] = errors.ToList(); - if (EnsureCanCreateSubDirectory(Current.Configs.Global().UmbracoMediaPath, out errors) == false) + if (EnsureCanCreateSubDirectory(_globalSettings.UmbracoMediaPath, out errors) == false) report["Media folder creation failed"] = errors.ToList(); } @@ -129,8 +131,7 @@ namespace Umbraco.Web.Install public bool TestPublishedSnapshotService(out IEnumerable errors) { - var publishedSnapshotService = Current.PublishedSnapshotService; - return publishedSnapshotService.EnsureEnvironment(out errors); + return _publishedSnapshotService.EnsureEnvironment(out errors); } // tries to create a sub-directory diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index fb809d1bfc..8be0af629e 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Install { private static HttpClient _httpClient; private readonly DatabaseBuilder _databaseBuilder; - private readonly HttpContextBase _httpContext; + private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger _logger; private readonly IGlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; @@ -29,7 +29,7 @@ namespace Umbraco.Web.Install DatabaseBuilder databaseBuilder, ILogger logger, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IConnectionStrings connectionStrings) { - _httpContext = httpContextAccessor.HttpContext; + _httpContextAccessor = httpContextAccessor; _logger = logger; _globalSettings = globalSettings; _umbracoVersion = umbracoVersion; @@ -42,16 +42,18 @@ namespace Umbraco.Web.Install return _installationType ?? (_installationType = IsBrandNewInstall ? InstallationType.NewInstall : InstallationType.Upgrade).Value; } - internal void InstallStatus(bool isCompleted, string errorMsg) + public void InstallStatus(bool isCompleted, string errorMsg) { + + var httpContext = _httpContextAccessor.HttpContext; try { - var userAgent = _httpContext.Request.UserAgent; + var userAgent = httpContext.Request.UserAgent; // Check for current install Id var installId = Guid.NewGuid(); - var installCookie = _httpContext.Request.GetCookieValue(Constants.Web.InstallerCookieName); + var installCookie = httpContext.Request.GetCookieValue(Constants.Web.InstallerCookieName); if (string.IsNullOrEmpty(installCookie) == false) { if (Guid.TryParse(installCookie, out installId)) @@ -61,7 +63,7 @@ namespace Umbraco.Web.Install installId = Guid.NewGuid(); } } - _httpContext.Response.Cookies.Set(new HttpCookie(Constants.Web.InstallerCookieName, "1")); + httpContext.Response.Cookies.Set(new HttpCookie(Constants.Web.InstallerCookieName, "1")); var dbProvider = string.Empty; if (IsBrandNewInstall == false) @@ -134,7 +136,7 @@ namespace Umbraco.Web.Install } } - internal IEnumerable GetStarterKits() + public IEnumerable GetStarterKits() { if (_httpClient == null) _httpClient = new HttpClient(); diff --git a/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs b/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs index 81407afe50..5847250b41 100644 --- a/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs +++ b/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs @@ -1,6 +1,6 @@ using System; using System.Threading; -using Umbraco.Core.Security; + namespace Umbraco.Web.Security { diff --git a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs index fd05f7cfbd..843a1cef0c 100644 --- a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs @@ -1,11 +1,18 @@ using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; +using Umbraco.Web.Routing; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -23,6 +30,24 @@ namespace Umbraco.Web.Trees [CoreTree] public class ContentBlueprintTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public ContentBlueprintTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { @@ -89,7 +114,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index bb7613422e..9b64111b85 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -42,6 +42,7 @@ namespace Umbraco.Web.Trees private readonly UmbracoTreeSearcher _treeSearcher; private readonly ActionCollection _actions; private readonly IGlobalSettings _globalSettings; + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; protected override int RecycleBinId => Constants.System.RecycleBinContent; @@ -64,12 +65,14 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider, menuItemCollectionFactory) { _treeSearcher = treeSearcher; _actions = actions; _globalSettings = globalSettings; + _menuItemCollectionFactory = menuItemCollectionFactory; } /// @@ -133,7 +136,7 @@ namespace Umbraco.Web.Trees { if (id == Constants.System.RootString) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); // if the user's start node is not the root then the only menu item to display is refresh if (UserStartNodes.Contains(Constants.System.Root) == false) @@ -184,7 +187,7 @@ namespace Umbraco.Web.Trees //if the user has no path access for this node, all they can do is refresh if (!Security.CurrentUser.HasContentPathAccess(item, Services.EntityService)) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -246,7 +249,7 @@ namespace Umbraco.Web.Trees /// protected MenuItemCollection GetAllNodeMenuItems(IUmbracoEntity item) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); AddActionNode(item, menu, opensDialog: true); AddActionNode(item, menu, opensDialog: true); AddActionNode(item, menu, opensDialog: true); @@ -282,7 +285,7 @@ namespace Umbraco.Web.Trees /// protected MenuItemCollection GetNodeMenuItemsForDeletedContent(IUmbracoEntity item) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(Services.TextService, opensDialog: true); diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index 71196b84c3..7646a71e7d 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -28,6 +28,8 @@ namespace Umbraco.Web.Trees { public abstract class ContentTreeControllerBase : TreeController { + public IMenuItemCollectionFactory MenuItemCollectionFactory { get; } + protected ContentTreeControllerBase( IGlobalSettings globalSettings, @@ -39,9 +41,11 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) { + MenuItemCollectionFactory = menuItemCollectionFactory; } protected ContentTreeControllerBase() @@ -430,7 +434,7 @@ namespace Umbraco.Web.Trees deleteAllowed = perms.FirstOrDefault(x => x.Contains(deleteAction.Letter)) != null; } - var menu = new MenuItemCollection(); + var menu = MenuItemCollectionFactory.Create(); // only add empty recycle bin if the current user is allowed to delete by default if (deleteAllowed) { diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index f150eb8ba0..afd89f967a 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -27,6 +27,7 @@ namespace Umbraco.Web.Trees public class ContentTypeTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; public ContentTypeTreeController( UmbracoTreeSearcher treeSearcher, @@ -39,10 +40,12 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) { _treeSearcher = treeSearcher; + _menuItemCollectionFactory = menuItemCollectionFactory; } protected override TreeNode CreateRootNode(FormDataCollection queryStrings) @@ -103,7 +106,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs index 7c4da2cf0f..100a5ffe7a 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs @@ -29,6 +29,7 @@ namespace Umbraco.Web.Trees public class DataTypeTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; public DataTypeTreeController( UmbracoTreeSearcher treeSearcher, @@ -41,10 +42,12 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) { _treeSearcher = treeSearcher; + _menuItemCollectionFactory = menuItemCollectionFactory; } protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) @@ -128,7 +131,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web/Trees/DictionaryTreeController.cs index 3f7b89bcdf..b8d16062ba 100644 --- a/src/Umbraco.Web/Trees/DictionaryTreeController.cs +++ b/src/Umbraco.Web/Trees/DictionaryTreeController.cs @@ -2,9 +2,16 @@ using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Routing; using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Trees @@ -21,6 +28,25 @@ namespace Umbraco.Web.Trees [Tree(Constants.Applications.Translation, Constants.Trees.Dictionary, TreeGroup = Constants.Trees.Groups.Settings)] public class DictionaryTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public DictionaryTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } + protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { var root = base.CreateRootNode(queryStrings); @@ -100,7 +126,7 @@ namespace Umbraco.Web.Trees /// protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); menu.Items.Add(Services.TextService, opensDialog: true); diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index 9bbe05b0ce..bacfc820d6 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -4,14 +4,46 @@ using System.Linq; using System.Net.Http.Formatting; using System.Web; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.Composing; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Routing; namespace Umbraco.Web.Trees { public abstract class FileSystemTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + protected FileSystemTreeController() + { + _menuItemCollectionFactory = Current.MenuItemCollectionFactory; + } + + protected FileSystemTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } + protected abstract IFileSystem FileSystem { get; } protected abstract string[] Extensions { get; } protected abstract string FileIcon { get; } @@ -88,7 +120,7 @@ namespace Umbraco.Web.Trees protected virtual MenuItemCollection GetMenuForRootNode(FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; @@ -102,7 +134,7 @@ namespace Umbraco.Web.Trees protected virtual MenuItemCollection GetMenuForFolder(string path, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; @@ -126,7 +158,7 @@ namespace Umbraco.Web.Trees protected virtual MenuItemCollection GetMenuForFile(string path, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); //if it's not a directory then we only allow to delete the item menu.Items.Add(Services.TextService, opensDialog: true); @@ -142,7 +174,7 @@ namespace Umbraco.Web.Trees return GetMenuForRootNode(queryStrings); } - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); var path = string.IsNullOrEmpty(id) == false && id != Constants.System.RootString ? HttpUtility.UrlDecode(id).TrimStart("/") diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index cbe1946779..5c03e11c37 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -1,10 +1,17 @@ using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Umbraco.Web.Actions; +using Umbraco.Web.Routing; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -15,6 +22,25 @@ namespace Umbraco.Web.Trees [CoreTree] public class MacrosTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public MacrosTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } + protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { var root = base.CreateRootNode(queryStrings); @@ -46,7 +72,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { @@ -60,7 +86,7 @@ namespace Umbraco.Web.Trees } var macro = Services.MacroService.GetById(int.Parse(id)); - if (macro == null) return new MenuItemCollection(); + if (macro == null) return menu; //add delete option for all macros menu.Items.Add(Services.TextService, opensDialog: true); diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs index 6983e84dd8..05b7e0e2ad 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTreeController.cs @@ -52,8 +52,9 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider, menuItemCollectionFactory) { _treeSearcher = treeSearcher; } @@ -99,7 +100,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = MenuItemCollectionFactory.Create(); //set the default menu.DefaultMenuAlias = ActionNew.ActionAlias; diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs index 1c7f6ca3ae..d89e93bb49 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs @@ -27,6 +27,7 @@ namespace Umbraco.Web.Trees public class MediaTypeTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; public MediaTypeTreeController( UmbracoTreeSearcher treeSearcher, @@ -39,10 +40,12 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) { _treeSearcher = treeSearcher; + _menuItemCollectionFactory = menuItemCollectionFactory; } protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) @@ -87,7 +90,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index 84909d5fda..490fe3d646 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -7,7 +7,12 @@ using System.Net.Http.Formatting; using System.Web.Http; using System.Web.Http.ModelBinding; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Security; using Umbraco.Web.Actions; @@ -15,6 +20,7 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Routing; using Umbraco.Web.Search; using Constants = Umbraco.Core.Constants; using Umbraco.Web.Security; @@ -33,12 +39,29 @@ namespace Umbraco.Web.Trees [SearchableTree("searchResultFormatter", "configureMemberResult")] public class MemberTreeController : TreeController, ISearchableTree { - public MemberTreeController(UmbracoTreeSearcher treeSearcher) - { - _treeSearcher = treeSearcher; - } + private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public MemberTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + UmbracoTreeSearcher treeSearcher, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _treeSearcher = treeSearcher; + _menuItemCollectionFactory = menuItemCollectionFactory; + } /// /// Gets an individual tree node @@ -111,7 +134,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { diff --git a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs index 5e71266bca..e54b200fea 100644 --- a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs @@ -1,8 +1,16 @@ using System.Collections.Generic; using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.Composing; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Routing; namespace Umbraco.Web.Trees { @@ -10,6 +18,30 @@ namespace Umbraco.Web.Trees [CoreTree] public abstract class MemberTypeAndGroupTreeControllerBase : TreeController { + public IMenuItemCollectionFactory MenuItemCollectionFactory { get; } + + protected MemberTypeAndGroupTreeControllerBase() + { + MenuItemCollectionFactory = Current.MenuItemCollectionFactory; + } + + protected MemberTypeAndGroupTreeControllerBase( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + MenuItemCollectionFactory = menuItemCollectionFactory; + } + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) { var nodes = new TreeNodeCollection(); @@ -19,7 +51,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = MenuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web/Trees/PackagesTreeController.cs index 90a41c050c..5608196109 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web/Trees/PackagesTreeController.cs @@ -1,7 +1,14 @@ using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; +using Umbraco.Web.Routing; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -13,6 +20,25 @@ namespace Umbraco.Web.Trees [CoreTree] public class PackagesTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public PackagesTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } + /// /// Helper method to create a root model for a tree /// @@ -39,7 +65,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { //doesn't have a menu, this is a full screen app without tree nodes - return MenuItemCollection.Empty; + return _menuItemCollectionFactory.Create(); } } } diff --git a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs index 9fa0c025d6..e1e848df76 100644 --- a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs +++ b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs @@ -1,6 +1,5 @@ using Umbraco.Core.IO; using Umbraco.Web.Composing; -using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index d2d2253f20..5601af0da3 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -3,8 +3,14 @@ using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.Routing; namespace Umbraco.Web.Trees { @@ -14,11 +20,30 @@ namespace Umbraco.Web.Trees [CoreTree] public class RelationTypeTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public RelationTypeTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { //TODO: Do not allow deleting built in types - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); if (id == Constants.System.RootString) { @@ -32,7 +57,7 @@ namespace Umbraco.Web.Trees } var relationType = Services.RelationService.GetRelationTypeById(int.Parse(id)); - if (relationType == null) return new MenuItemCollection(); + if (relationType == null) return menu; menu.Items.Add(Services.TextService); diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index 6c8b23030e..647683e5c5 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -29,6 +29,7 @@ namespace Umbraco.Web.Trees public class TemplatesTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; public TemplatesTreeController( UmbracoTreeSearcher treeSearcher, @@ -41,10 +42,12 @@ namespace Umbraco.Web.Trees IRuntimeState runtimeState, UmbracoHelper umbracoHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) { _treeSearcher = treeSearcher; + _menuItemCollectionFactory = menuItemCollectionFactory; } protected override TreeNode CreateRootNode(FormDataCollection queryStrings) @@ -97,7 +100,7 @@ namespace Umbraco.Web.Trees /// protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); + var menu = _menuItemCollectionFactory.Create(); //Create the normal create action var item = menu.Items.Add(Services.TextService, opensDialog: true); @@ -112,7 +115,7 @@ namespace Umbraco.Web.Trees } var template = Services.FileService.GetTemplate(int.Parse(id)); - if (template == null) return new MenuItemCollection(); + if (template == null) return menu; var entity = FromTemplate(template); //don't allow delete if it has child layouts diff --git a/src/Umbraco.Web/Trees/UserTreeController.cs b/src/Umbraco.Web/Trees/UserTreeController.cs index 475fbad2a8..648e9ef29c 100644 --- a/src/Umbraco.Web/Trees/UserTreeController.cs +++ b/src/Umbraco.Web/Trees/UserTreeController.cs @@ -1,7 +1,14 @@ using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Mapping; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; +using Umbraco.Web.Routing; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -13,6 +20,25 @@ namespace Umbraco.Web.Trees [CoreTree] public class UserTreeController : TreeController { + private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; + + public UserTreeController( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger logger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + UmbracoMapper umbracoMapper, + IPublishedUrlProvider publishedUrlProvider, + IMenuItemCollectionFactory menuItemCollectionFactory) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, umbracoMapper, publishedUrlProvider) + { + _menuItemCollectionFactory = menuItemCollectionFactory; + } + /// /// Helper method to create a root model for a tree /// @@ -38,7 +64,7 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { //doesn't have a menu, this is a full screen app without tree nodes - return MenuItemCollection.Empty; + return _menuItemCollectionFactory.Create(); } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b6b48e7755..f549ae4622 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -134,17 +134,16 @@ - - - + + + - @@ -154,12 +153,11 @@ - - - + + @@ -178,22 +176,17 @@ - - - - - - - - - - - + + + + + + @@ -222,7 +215,6 @@ - @@ -290,9 +282,6 @@ - - - @@ -399,30 +388,8 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 3087630edd..b20ebe7e09 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -10,18 +10,21 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Web.Features; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.WebApi { + + /// /// Provides a base class for Umbraco API controllers. /// /// These controllers are NOT auto-routed. [FeatureAuthorize] - public abstract class UmbracoApiControllerBase : ApiController + public abstract class UmbracoApiControllerBase : ApiController, IUmbracoFeature { // note: all Umbraco controllers have two constructors: one with all dependencies, which should be used,